full-disclosure-uk August 2008 archive
Main Archive Page > Month Archives  > full-disclosure-uk archives
full-disclosure-uk: [Full-disclosure] Vim: Unfixed Vulnerabiliti

[Full-disclosure] Vim: Unfixed Vulnerabilities in Tar Plugin Version 20

From: Jan Minář <rdancer_at_nospam>
Date: Fri Aug 08 2008 - 14:29:53 GMT
To: bugs@vim.org, vim-dev@vim.org, full-disclosure@lists.grok.org.uk, bugtraq@securityfocus.com, "Charles E Campbell, Jr (Vim Tar Plugin Maintainer)" <drchip@campbellfamily.biz>


Vim: Unfixed Vulnerabilities in Tar Plugin Version 20

  1. SUMMARY
Product : Vim -- Vi IMproved
Version : Vim >= 7.0 (possibly older), present in 7.2c.002

           autoload/tar.vim >= 9 (possibly older), present in version 20 Impact : Arbitrary code execution Wherefrom: Local, remote CVE : CVE-2008-2712 Original : http://www.rdancer.org/vulnerablevim-tarplugin-update.html

The Vim Tar Plugin vulnerabilities published in our previous advisories have been addressed, but the changes do not provide fix for all attack vectors. We analyses some of the vulnerabilities remaining in ``$VIMRUNTIME/autoload/tar.vim''.

2. BACKGROUND   ``Vim is an almost compatible version of the UNIX editor Vi. Many new     features have been added: multi-level undo, syntax highlighting,     command line history, on-line help, spell checking, filename     completion, block operations, etc.''

  • Vim README.txt

 ``When one edits a *.tar file, this plugin will handle displaying a    contents page. Select a file to edit by moving the cursor atop    the desired file, then hit the <return> key. After editing, one may    also write to the file.''

  • Tar File Interface (pi_tar.txt) 3. ATTEMPTED FIX
These are all the ``execute'' and system() calls in the current code (autoload/tar.vim version 20, 2008-07-30) code. It can be seen that all the vulnerable statements have been changed. Unfortunately, not all the changes provide a sufficient fix. (We analyse the vulnerabilities in section 4 below):

    133 let tarfile=substitute(system("cygpath -u
".s:Escape(tarfile,0)),'\n$','','e')
138 exe "silent r! gzip -d -c -- ".s:Escape(tarfile,1)." |
".g:tar_cmd." -".g:tar_browseoptions." - "
141 exe "silent r! cat -- ".s:Escape(tarfile,1)."|gzip -d -c -|".g:tar_cmd." -".g:tar_browseoptions." - " 144 exe "silent r! bzip2 -d -c -- ".s:Escape(tarfile,1)." |
".g:tar_cmd." -".g:tar_browseoptions." - "
147 exe "silent r! ".g:tar_cmd." -".g:tar_browseoptions."
".s:Escape(tarfile,1)
163 exe "r ".fnameescape(a:tarfile) 198 let tarfile=substitute(system("cygpath -u
".s:Escape(tarfile,0)),'\n$','','e')
223 let tarfile=substitute(system("cygpath -u
".s:Escape(tarfile,0)),'\n$','','e')
244 exe "silent r! gzip -d -c -- ".s:Escape(tarfile,1)."|
".g:tar_cmd." -".g:tar_readoptions." - ".s:Escape(fname,1).decmp
247 exe "silent r! cat -- ".s:Escape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".s:Escape(fname,1).decmp 250 exe "silent r! bzip2 -d -c -- ".s:Escape(tarfile,1)."|
".g:tar_cmd." -".g:tar_readoptions." - ".s:Escape(fname,1).decmp
253 exe "silent r! ".g:tar_cmd." -".g:tar_readoptions."
".s:Escape(tarfile,1)." -- ".s:Escape(fname,1).decmp
262 exe "file tarfile::".fnameescape(fname) 308 exe "cd ".fnameescape(tmpdir) 332 call system("gzip -d -- ".s:Escape(tarfile,0)) 336 call system("gzip -d -- ".s:Escape(tarfile,0)) 341 call system("bzip2 -d -- ".s:Escape(tarfile,0)) 359 let dirpath = substitute(system("cygpath
".s:Escape(dirpath, 0)),'\n','','e')
368 exe "w! ".fnameescape(fname) 370 let tarfile = substitute(system("cygpath
".s:Escape(tarfile,0)),'\n','','e')
375 call system("tar --delete -f ".s:Escape(tarfile,0)." --
".s:Escape(fname,0))
384 call system("tar -".g:tar_writeoptions."
".s:Escape(tarfile,0)." -- ".s:Escape(fname,0))
391 call system(compress) 407 exe "e! ".fnameescape(tarfile) 419 exe "cd ".fnameescape(curdir) 431 call system("/bin/rm -rf -- ".s:Escape(a:fname,0)) 434 call system("/bin/rm -rf -- ".s:Escape(a:fname,0)) 436 call system("del /S ".s:Escape(a:fname,0))

This is the listing from section ``3.4.2.3.1.'' of the original advisory[1], for reference: 99 exe "$put ='".'\"'." Browsing tarfile ".a:tarfile."'" 107 let tarfile=substitute(system("cygpath -u ".tarfile),'\n$','','e') 112 exe "silent r! gzip -d -c ".g:tar_shq.tarfile.g:tar_shq."|
".g:tar_cmd." -".g:tar_browseoptions." - "
115 exe "silent r! bzip2 -d -c ".g:tar_shq.tarfile.g:tar_shq."|
".g:tar_cmd." -".g:tar_browseoptions." - "
118 exe "silent r! ".g:tar_cmd." -".g:tar_browseoptions."
".g:tar_shq.tarfile.g:tar_shq
134 exe "r ".a:tarfile 169 let tarfile=substitute(system("cygpath -u ".tarfile),'\n$','','e') 192 let tarfile=substitute(system("cygpath -u ".tarfile),'\n$','','e') 199 exe "silent r! gzip -d -c ".g:tar_shq.tarfile.g:tar_shq."|
".g:tar_cmd." -".g:tar_readoptions." - '".fname."'"
202 exe "silent r! bzip2 -d -c ".g:tar_shq.tarfile.g:tar_shq."|
".g:tar_cmd." -".g:tar_readoptions." - '".fname."'"
205 exe "silent r! ".g:tar_cmd." -".g:tar_readoptions."
".g:tar_shq.tarfile.g:tar_shq." ".g:tar_shq.fname.g:tar_shq
208 exe "file tarfile:".fname 278 call system("gzip -d ".tarfile) 282 call system("gzip -d ".tarfile) 287 call system("bzip2 -d ".tarfile) 303 let dirpath = substitute(system("cygpath ".dirpath),'\n','','e') 312 exe "w! ".fname 314 let tarfile = substitute(system("cygpath ".tarfile),'\n','','e') 319 call system("tar --delete -f '".tarfile."' '".fname."'") 335 call system(compress) 351 exe "e! ".tarfile

4. VULNERABILITIES 4.1. Untrusted File Names Interpreted as Optional Argument

4.1.1. POSIX Systems

The POSIX end-of-options double-dash (--) is missing from some of the commands invoked by system() -- line 244 a.o.:

    244 exe "silent r! gzip -d -c -- ".s:Escape(tarfile,1)."|
".g:tar_cmd." -".g:tar_readoptions." - ".s:Escape(fname,1).decmp

The resulting command looks like this:

    gzip -d -c -- TARBALL | tar -OPxf - MEMBER

MEMBER can be interpreted by tar(1) as a command line option. This can be still used to execute arbitrary shell commands (cf. e.g. the ``--compress-program'' option of tar(1)).

4.1.2. Other Systems

With implementations of tar(1) (and other programs) that do not understand the double-dash convention, another mechanism must be used to prevent the file name from being interpreted as command line options. At the same time, the current code may confuse such programs.

It is not possible for Vim to know the invocation syntax of external programs. As the double-dash security measure may not be present in any given external command, the security of commands that pass untrusted input to these external commands is not be guaranteed.

4.2 Unspecified Behaviour of system() and ``!''

4.2.1. The system() Function

system(), does not invoke /bin/sh to run the commands, as does the C Standard Library function of the same name. Rather, it uses the program specified in the Vim internal option 'shell'. The full details of how system() works can be found in the Vim Manual:

  ``system({expr} [, {input}]) *system()* *E677*     [...]
    The command executed is constructed using several options:     'shell' 'shellcmdflag' 'shellxquote' {expr} 'shellredir' {tmp} 'shellxquote'     ({tmp} is an automatically generated file name). For Unix and OS/2     braces are put around {expr} to allow for concatenated commands.''

  • Vim Reference Manual (``eval.txt'')

As the particularities of how this program interprets the command can not be known, it is inherently impossible to say anything meaningful as to whether there are security issues. In fact, it is not possible to say anything about how the command will be interpreted, or if it will be interpreted at all. In the absence of a baseline specification, the behaviour of system() as implemented by Vim can only be described as "unspecified".

By setting the respective options to known values, it may be possible to reach the C Standard Library system() functionality. There will still be problems on systems without /bin/sh, and on systems where /bin/sh is not POSIX-conformant.

4.2.2. The ``!'' Command

The same applies to the ``!'' command, as used e.g. on line 138:

    138 exe "silent r! gzip -d -c -- ".s:Escape(tarfile,1)." |
".g:tar_cmd." -".g:tar_browseoptions." - "

The ``r!'' means the ``read'' command reads the output of the ``!'' command, which in turn executes shell commands, in a way similar to system().

5. EXPLOIT No exploit code is provided.

6. REFERENCES [1] Collection of Vulnerabilities in Fully Patched Vim 7.1

    http://www.rdancer.org/vulnerablevim.html

7. COPYRIGHT This advisory is Copyright 2008 Jan Minar <rdancer@rdancer.org>

Copying welcome, under the Creative Commons ``Attribution-Share Alike'' License http://creativecommons.org/licenses/by-sa/2.0/uk/

Code included herein, and accompanying this advisory, may be copied according to the GNU General Public License version 2, or the Vim license. See the subdirectory ``licenses''.

Various portions of the accompanying code were written by various parties. Those parties may hold copyright, and those portions may be copied according to their respective licenses.

8. HISTORY 2008-08-08 Sent to: <bugs@vim.org>, <vim-dev@vim.org>, <full-disclosure@lists.grok.org.uk>, <bugtraq@securityfocus.com>, Charles E Campbell, Jr (Vim Tar Plugin Maintainer) <drchip@campbellfamily.biz> _______________________________________________ Full-Disclosure - We believe in it.
Charter: http://lists.grok.org.uk/full-disclosure-charter.html Hosted and sponsored by Secunia - http://secunia.com/