[prev in list] [next in list] [prev in thread] [next in thread]
List: oss-security
Subject: [oss-security] Re: More arbitrary code executions in Netrw version 125, Vim 7.2a.10
From: Bram Moolenaar <Bram () moolenaar ! net>
Date: 2008-07-07 19:05:37
Message-ID: 200807071905.m67J5blB065410 () moolenaar ! net
[Download RAW message or body]
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.'@'.g: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@Moolenaar.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 ///
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic