|
Message-ID: <4871D3AE.4070004@freethemallocs.com> Date: Mon, 07 Jul 2008 00:28:30 -0800 From: Jonathan Smith <smithj@...ethemallocs.com> To: vim_dev@...glegroups.com, "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 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. > > --~--~---------~--~----~------------~-------~--~----~ > 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) iEYEAREIAAYFAkhx054ACgkQCG91qXPaRektJwCgpWWPsqaiH1fkgqAlqsKm+VIF JSQAoILE62WZnh2raUk0yHWwx2lVhk57 =jzec -----END PGP SIGNATURE-----
Powered by blists - more mailing lists
Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.