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-next>] [month] [year] [list]
Date: Mon, 07 Jul 2008 00:40:21 -0800
From: Jonathan Smith <smithj@...ethemallocs.com>
To: Bram@...lenaar.net, "Steven M. Christey" <coley@...us.mitre.org>
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

-----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.
>
> --~--~---------~--~----~------------~-------~--~----~
> You received this message from the "vim_dev" maillist.
> For more information, visit http://www.vim.org/maillist.php
> -~----------~----~----~----~------~----~------~--~---


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.

Thanks in advance to you both.

Also potentially of interest: on rPath Linux 2 and Foresight Linux 2, I
get the following with vim 7.1 (it could be due either to version skew
between me and the reporter or due to how we build vim):

tarplugin.updated: VULNERABLE
zipplugin : VULNERABLE
netrw.v2  : EXPLOIT FAILED
netrw.v3  : EXPLOIT FAILED
netrw.v4  : EXPLOIT FAILED

On rPath Linux 1, with vim 6.3, I get the following:

tarplugin.updated: EXPLOIT FAILED
zipplugin : EXPLOIT FAILED
netrw.v2  : EXPLOIT FAILED
netrw.v3  : EXPLOIT FAILED
netrw.v4  : EXPLOIT FAILED

	smithj

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (GNU/Linux)

iEYEAREIAAYFAkhx1nQACgkQCG91qXPaReloxACgkuXu4cmQrlNA94bfsVtySTOj
NjYAn2C9G84G6/yheXH2UXrk3OmCuTGH
=bEnw
-----END PGP SIGNATURE-----

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