一. 漏洞背景
Vim和Neovim是Unix类操作系统下广泛使用的跨平台文本编辑器,其中Neovim是基于Vim开发的。
Vim/Neovim中的modeline功能可以让用户在文本文件的开头或结尾使用特定代码来控制编辑器的一些行为。这个功能被限制到仅能执行特定set指令,且有沙箱隔离,但:source!指令却可以用来绕过沙箱执行命令。
- 漏洞编号: CVE-2019-12735
- 受影响版本:Vim < 8.1.1365, Neovim < 0.3.6
二. 漏洞成因
Modeline功能会将所有含表达式的语句在沙箱中执行,可能的选项包括’foldexpr’, ‘formatexpr’, ‘includeexpr’, ‘indentexpr’, ‘statusline’和 ‘foldtext’。
Modeline的常见格式如下:
但是:source!命令可以用来绕过沙箱。当使用:source!命令时,vim会从指定文件读入vimscript代码并执行:
如果我们在沙箱中执行:source!命令的话,沙箱可以被绕过。在patch 8.1.1365之前,我们可以在vim modeline中的expression调用:source!来执行任意vim脚本,这一过程如上面的vim文档所说,就像你在normal模式下手动输入执行命令一样,是没有沙箱限制的。
Vim释出的补丁patch 8.1.1365中增加了对:source!命令的沙箱环境判断,拒绝在沙箱中执行。
所以,我们可以在modeline中使用:source!命令来执行一个vim脚本:
上图中使用foldexpr选项实现了表达式执行,整个modeline的作用是设置基于expression的foldmethod。
三. 漏洞利用
考虑到作为攻击者,无法事先写好要执行的vim脚本并存储在目标磁盘上,我们就无法通过:source!执行需要的命令。
为了直接执行命令,这里使用了一个技巧:
:source! %会把当前文件的内容当作vim脚本执行,所以,下图中的exec.txt实际上会被vim的:source!当作:!echo vim_pwned || garbage_string来执行,根据bash语法(执行前半句失败则执行后半句),最后执行了前半句的echo。
如图,这样就实现了任意代码执行。