Openwall Project   /home  Owl  JtR  Pro  crypt  pam_passwdqc  tcb  phpass  scanlogd  popa3d  msulogin  /  Linux  BIND  /  advisories  presentations  /  services  donations  /  wordlists  passwords  /  news  community  lists  wiki  CVSweb  mirrors  signatures
bringing security into open environments
 
Password Recovery Resources on the Net
[<prev] [next>] [<thread-prev] [month] [year] [list]
Date: Mon, 07 Jul 2008 21:05:37 +0200
From: Bram Moolenaar <Bram@...lenaar.net>
To: Jonathan Smith <smithj@...ethemallocs.com>
CC: "Charles E Campbell, Jr" <drchip@...pbellfamily.biz>,
        oss-security@...ts.openwall.com
Subject: Re: More arbitrary code executions in Netrw version 125, Vim 7.2a.10


Jonathan -

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA256
> 
> Forgive the double-post; my first message was blocked by the vim_dev
> mailing list due to not being subscribed (which is very odd, given that
> I am subscribed). This one is being sent directly to Bram instead.
> 
> 	smithj
> 
> Jan MinĂ¡Å. wrote:
> > Following my recent advisory on Vim vulnerabilities, here goes a followup: many
> > more vulnerabile statements in Netrw.  Although Netrw has been updated with
> > the new fnameescape() and shellescape() functions, it doesn't use them
> > consistently.  It is difficult *not* to find vulnerable code in Netrw.
> >
> > This writeup can be found at:
> > 	``http://www.rdancer.org/vulnerablevim-netrw.html''
> > The archive with code that we're using can be found at:
> > 	``http://www.rdancer.org/vulnerablevim-netrw.tar.bz2''.
> >
> > Best results are achieved by running ``make test'' in the root
> > directory of the abovementioned archive:
> >
> > 	$ make test
> > 	[...]
> >         -------------------------------------------
> >         -------- Test results below ---------------
> >         -------------------------------------------
> >         filetype.vim
> >         tarplugin.updated: VULNERABLE
> >         zipplugin : VULNERABLE
> >     --> netrw.v2  : VULNERABLE
> >     --> netrw.v3  : VULNERABLE
> >     --> netrw.v4  : VULNERABLE
> >
> >
> > 1. Compression and Decompression (The ``mz'' Command)
> >
> > Invoking the ``mz'' command upon a file with a crafted file name can lead to
> > arbitrary code execution.
> >
> >
> > 1.1 Vulnerability
> >
> > In many places, Netrw ($VIMRUNTIME/autoload/netrw.vim) fails to sanitize file
> > names used as shell arguments.
> >
> > In function s:NetrwMarkFileExe() (The ``mx'' command): ``apply command to marked
> > files.  Substitute: filename -> % If no %, then append a space and the filename
> > to the command'':
> >
> >         4036    for fname in s:netrwmarkfilelist_{curbufnr}
> >         4037     if a:islocal
> >         4038      if g:netrw_keepdir
> >         4039       let fname= s:ComposePath(curdir,fname)
> >         4040      endif
> >         4041     else
> >         4042      let fname= b:netrw_curdir.fname
> >         4043     endif
> >         4044     if cmd =~ '%'
> >         4045      let xcmd= substitute(cmd,'%',fname,'g')
> >         4046     else
> >         4047      let xcmd= cmd.' '.fname
> >         4048     endif
> >         4049     if a:islocal
> >         4050 "     call Decho("local: xcmd<".xcmd.">")
> >     --> 4051      let ret= system(xcmd)
> >         4052     else
> >         4053 "     call Decho("remote: xcmd<".xcmd.">")
> >     --> 4054      let ret= s:RemoteSystem(xcmd)
> >
> > Following code in function s:NetrwMarkFileCompress() is run when the ``mz''
> > (compress/decompress) command is invoked.  The variable
> > ``s:netrwmarkfilelist_{curbufnr}'' holds the marked files list.:
> >
> > 	 159 if !exists("g:netrw_decompress")
> > 	 160  let g:netrw_decompress= { ".gz" : "gunzip" , ".bz2" : "bunzip2"
> > , ".zip" : "unzip" , ".tar" : "tar -xf"}
> > 	 161 endif
> > 	[...]
> >         3816    for fname in s:netrwmarkfilelist_{curbufnr}
> >         3817     " for every filename in the marked list
> >         3818     for sfx in sort(keys(g:netrw_decompress))
> >         3819      if fname =~ '\'.sfx.'$'
> >         3820       " fname has a suffix indicating that its
> > compressed; apply associated decompression routine
> >         3821       let exe= g:netrw_decompress[sfx]
> >         3822 "      call Decho("fname<".fname."> is compressed so
> > decompress with <".exe.">")
> >         3823       if a:islocal
> >         3824        if g:netrw_keepdir
> >         3825         let fname= s:ComposePath(curdir,fname)
> >         3826        endif
> >         3827       else
> >         3828        let fname= b:netrw_curdir.fname
> >         3829       endif
> >         3830       if executable(exe)
> >         3831        if a:islocal
> >     --> 3832         call system(exe." ".fname)
> >
> >
> > 1.2. Exploit
> >
> > We exploit the statement on line 3832.
> >
> > Run ``make demo'' or ``make test'' in the netrw.v2 directory.  Note: ``make
> > test'' may hang when run from within vim.
> >
> >
> > 2. Copying Files (The ``mc'' Command)
> >
> > Invoking the ``mc'' command inside a directory with a crafted directory name
> > can lead to arbitrary code execution.
> >
> >
> > 2.1. Vulnerability
> >
> > Netrw inappropriately uses shellescape() in many places to sanitize
> > arguments of the
> > ``execute'' command.
> >
> >         708   exe s:netrw_silentxfer."!".g:netrw_rcp_cmd."
> > ".s:netrw_rcpmode."
> > ".shellescape(uid_machine.":".escape(b:netrw_fname,' ?&;')."
> > ".tmpfile)
> >         810    exe s:netrw_silentxfer."!".g:netrw_scp_cmd.useport."
> > ".shellescape(g:netrw_machine.":".escape(b:netrw_fname,g:netrw_fname_escape))."
> > ".tmpfile
> >         831     exe s:netrw_silentxfer."!".g:netrw_http_cmd."
> > ".shellescape(tmpfile)."
> > ".shellescape("http://".g:netrw_machine.netrw_fname)
> >         842     exe s:netrw_silentxfer."!".g:netrw_http_cmd."
> > ".shellescape(tmpfile)."
> > ".shellescape("http://".g:netrw_machine.netrw_html)
> >         882    exe s:netrw_silentxfer."!".g:netrw_rsync_cmd."
> > ".shellescape(g:netrw_machine.":".netrw_fname)." ".tmpfile
> >         907     exe s:netrw_silentxfer."!".g:netrw_fetch_cmd."
> > ".tmpfile." ".shellescape(netrw_option."://".g:netrw_uid.':'.s:netrw_passwd.'@...:netrw_machine."/".netrw_fname)
> >         910     exe s:netrw_silentxfer."!".g:netrw_fetch_cmd."
> > ".tmpfile." ".shellescape(netrw_option."://".g:netrw_machine."/".netrw_fname)
> >         923    exe s:netrw_silentxfer."!".g:netrw_sftp_cmd."
> > ".shellescape(g:netrw_machine.":".netrw_fname)." ".tmpfile
> >         1084    exe s:netrw_silentxfer."!".g:netrw_rcp_cmd."
> > ".s:netrw_rcpmode." ".shellescape(tmpfile)."
> > ".shellescape(uid_machine.":".netrw_fname)
> >         1177    exe s:netrw_silentxfer."!".g:netrw_scp_cmd.useport."
> > ".shellescape(tmpfile)."
> > ".shellescape(g:netrw_machine.":".netrw_fname)
> >         2976   exe "silent !".viewer." ".viewopt.shellescape(fname).redir
> >         2981   exe 'silent !start rundll32 url.dll,FileProtocolHandler
> > '.shellescape(fname)
> >         2987   exe "silent !gnome-open ".shellescape(fname).redir
> >         2992   exe "silent !kfmclient exec ".shellescape(fname)." ".redir
> >         2997   exe "silent !open ".shellescape(fname)." ".redir
> >         3656    exe "silent! !".g:netrw_local_mkdir.' '.shellescape(newdirname)
> >         3680   exe "silent! !".mkdircmd." ".shellescape(newdirname)
> >         3911    exe "silent! !".g:netrw_local_mkdir.' '.shellescape(tmpdir)
> >         4775    exe s:netrw_silentxfer."!".g:netrw_scp_cmd.useport."
> > ".filelist." ".shellescape(tgtdir)
> >         5058    exe s:netrw_silentxfer."!".g:netrw_scp_cmd.useport."
> > ".args." ".shellescape(machine.":".escape(tgt,g:netrw_fname_escape))
> >         6001    exe "silent r! ".listcmd.shellescape(s:path)
> >         6015     exe "silent r! ".listcmd.' "'.shellescape(s:path).'"'
> >
> >
> >         3888    let args=
> > join(map(copy(s:netrwmarkfilelist_{bufnr('%')}),"b:netrw_curdir.\"/\".shellescape(v:val)"))
> >         3889 "   call Decho("system(".g:netrw_localcopycmd." ".args."
> > ".shellescape(s:netrwmftgt).")")
> >     --> 3890    call system(g:netrw_localcopycmd." ".args."
> > ".shellescape(s:netrwmftgt))
> >
> > 2.2. Exploit
> >
> > Run ``make demo'' or ``make test'' in the netrw.v3 directory.  Note: ``make
> > test'' may hang when run from within vim.
> >
> >
> > 2.3. Patch
> >
> > --- /usr/local/share/vim/vim72a/autoload/netrw.vim      2008-07-01
> > 18:38:09.000000000 +0100
> > +++ -   2008-07-03 19:01:50.676582822 +0100
> > @@ -3885,7 +3885,7 @@
> >    if      a:islocal &&  s:netrwmftgt_islocal
> >        " Copy marked files, local directory to local directory
> >         "   call Decho("copy from local to local")
> >         -   let args=
> > join(map(copy(s:netrwmarkfilelist_{bufnr('%')}),"b:netrw_curdir.\"/\".shellescape(v:val)"))
> >         +   let args=
> > join(map(copy(s:netrwmarkfilelist_{bufnr('%')}),"shellescape(b:netrw_curdir).\"/\".shellescape(v:val)"))
> >          "   call Decho("system(".g:netrw_localcopycmd." ".args."
> > ".shellescape(s:netrwmftgt).")")
> >              call system(g:netrw_localcopycmd." ".args."
> > ".shellescape(s:netrwmftgt))
> >
> >
> >
> > 3. Deleting Files (The ``D'' Command)
> >
> > Applying the ``D'' to a file with a crafted file name, or inside a directory
> > with a crafted directory name, can lead to arbitrary code execution.
> >
> >
> > 3.1 Vulnerability
> >
> > Netrw fails to properly sanitize arguments passed to the s:System() function,
> > which is a wrapper for the ``execute'' command:
> >
> >         7596    fun! s:System(cmd,path)
> >         [...]
> >         7599      let path = a:path
> >         [...]
> >         7615        exe "let result= ".a:cmd."('".path."')"
> >
> > In  function s:NetrwLocalRmFile():
> >
> >         6724	fun! s:NetrwLocalRmFile(path,fname,all)
> >         [...]
> >         6730	  let rmfile= s:ComposePath(a:path,a:fname)
> >         [...]
> >     --> 6754	    let ret= s:System("delete",rmfile)
> >         [...]
> >     --> 6777	    call s:System("system",g:netrw_local_rmdir.'
> > '.shellescape(rmfile))
> >         [...]
> >     --> 6782	     let errcode= s:System("delete",rmfile)
> >         [...]
> >     --> 6788	       call s:System("system","rm ".shellescape(rmfile))
> >
> > In function s:NetrwLocalRmFile():
> >         6730   let rmfile= s:ComposePath(a:path,a:fname)
> >         [...]
> >     --> 6754     let ret= s:System("delete",rmfile)
> >         [...]
> >     --> 6777     call s:System("system",g:netrw_local_rmdir.'
> > '.shellescape(rmfile))
> >         6778 "    call Decho("v:shell_error=".v:shell_error)
> >         6779
> >         6780     if v:shell_error != 0
> >         6781 "     call Decho("2nd attempt to remove directory<".rmfile.">")
> >     --> 6782      let errcode= s:System("delete",rmfile)
> >         6783 "     call Decho("errcode=".errcode)
> >         6784
> >         6785      if errcode != 0
> >         6786       if has("unix")
> >         6787 "       call Decho("3rd attempt to remove directory<".rmfile.">")
> >     --> 6788        call s:System("system","rm ".shellescape(rmfile))
> >
> >
> > 3.2 Exploit
> >
> > We exploit the statement on the line 6754.  Run ``make demo'' or ``make test''
> > in the netrw.v4 directory.  Note: ``make test'' may hang when run from within
> > vim.  We use the TIOCSTY ioctl to simulate keyboard input in ``make test'' --
> > avoid touching the keyboard while ``make test'' is running.
> 
> 
> Steve, could we get CVEs assigned, please? I'd imagine we'd need three;
> one for the tarplugin issue, one for the zipplugin, and one for the
> netrw issues (which are similar enough to probably justify lumping them
> together).
> 
> Bram, have you had a chance to look at this yet? The advisory included a
> patch for one of the issues, but not others.

The problem in the zip plugin has already been fixed, but the file
wasn't distributed yet.  It's now on
ftp://ftp.vim.org/pub/vim/runtime/autoload/zip.vim

Charles is working on further problems with the netrw plugin.  I'm
waiting for this to make the Vim 7.2b BETA release.

- Bram

-- 
        Very funny, Scotty.  Now beam down my clothes.

 /// Bram Moolenaar -- Bram@...lenaar.net -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\        download, build and distribute -- http://www.A-A-P.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Hosted by DataForce ISP - Powered by Openwall GNU/*/Linux