作者:fenix@知道創宇 404 實驗室
日期:2019 年 6 月 11 日
英文版本:http://www.bjnorthway.com/956/
前言
Vim 是從 vi 發展出來的一個文本編輯器。代碼補全、編譯及錯誤跳轉等方便編程的功能特別豐富,在程序員中被廣泛使用,和 Emacs 并列成為類 Unix 系統用戶最喜歡的文本編輯器。Neovim 是一個基于 vim 源代碼的重構項目。
2019 年 06 月 04 日,Vim & neovim 被曝出任意代碼執行漏洞。攻擊者通過誘使受害者使用 vim 或者 neovim 打開一個精心制作的文件,可以在目標機器上執行任意命令。
該漏洞是由于啟用了 modeline 模式導致的,Vim & neovim 歷史上也多次曝出和 modeline 相關的漏洞。
原作者已經分析的很清楚了,本文權當總結一下,順便對歷史曝出的多個漏洞做一次完整的分析。(在 vim 環境下,neovim 類似)
modeline 詳解
既然都是和 modeline 相關的漏洞,那就有必要知道 modeline 是什么。
vim 一共有 4 種模式:正常模式、插入模式、命令模式、可視模式。
在正常模式中,按下 : 鍵,就可以進入命令模式。在命令模式中可以執行一些輸入并執行一些 vim 或插件提供的指令,就像在 shell 里一樣。這些指令包括設置環境、文件操作、調用某個功能、執行命令等等。例如設置不顯示行號:

如果有很多偏好設置,每次打開文件都手動設置就會顯得很繁瑣,這時候 .vimrc 就派上用場了,在啟動 vim 時,當前用戶根目錄下的 .vimrc 文件會被自動加載。

.vimrc 中的設置會對打開的所有文件生效,不便于對單個文件作個性化設置,modeline 應運而生。
vim 的 modeline 可以讓你針對每個文件進行文件級別的設置,這些設置是覆蓋當前用戶的 .vimrc 中的設置的。vim 默認關閉了 modeline,在 .vimrc 末尾追加 set modeline 即可打開。
如果 modeline 打開,vim 在打開文件時會解析文件開頭及末尾符合一定格式的設置行。
格式一:

格式二:

為了安全考慮,在 modeline 的設置中只支持 set 命令。

特殊的,foldexpr,formatexpr,includeexpr,indentexpr,statusline,foldtext 等選項的值可以是一個表達式,如果選項是在 modeline 中設置,表達式在沙箱中執行。沙箱實質上就是對表達式所能實現的功能做了限制,如在沙箱中不能執行 shell 命令、不能讀寫文件、不能修改緩沖區等等,如下:

vim 對于沙箱的實現也很簡單。
沙箱檢查函數 check_secure():

在 libcall、luaeval 等危險指令的開頭進行沙箱檢查,如果發現在沙箱中調用,直接 return 掉。

歷史曝出的幾個 rce 漏洞中,CVE-2002-1377 和 CVE-2019-12735 都是由于存在部分指令沒有檢查沙箱,導致在 modeline 模式中被濫用從而任意命令執行。下面將一一分析。
CVE-2002-1377
2002 年曝出的 vim 任意代碼執行漏洞,影響 6.0、6.1 版本。太過古老,環境難以重現,簡單說下原理。PoC 如下:
/* vim:set foldmethod=expr: */
/* vim:set foldexpr=confirm(libcall("/lib/libc.so.6","system","/bin/ls"),"ms_sux"): */
利用 libcall 指令調用 libc 庫中的 system 函數實現任意命令執行。

現在添加了沙箱檢查,modeline 下已經用不了 libcall 了:

CVE-2016-1248
8.0.0056 之前的 vim 未正確驗證 filetype、syntax 、keymap 選項的值,受害者在 modeline 開啟下打開特制的文件,則可能導致執行任意代碼。
從 github 克隆代碼,checkout 到 v8.0.0055 分支,編譯安裝。.vimrc 的配置如下:

驗證 PoC :
00000000: 2f2f 2076 696d 3a20 7365 7420 6674 3d00 // vim: set ft=.
00000010: 2165 6368 6f5c 2070 776e 6564 203a 200a !echo\ pwned : .
set verbose=20開啟所有日志,看下調用鏈:

autocommand 即“自動命令”,在發生某些事件時自動執行,類似于鉤子函數。
比如我們在命令模式中輸入 :set syntax=python, vim 就會在相應目錄中尋找和 python syntax 相關的 vmscript 并加載。

如果我們在 modeline 中設置了 filetype 或者 syntax,會執行 au! FileType * exe "set syntax=" . expand("<amatch>") 自動完成上述過程。首先刪除所有和 FileType 相關聯的自動命令,然后調用 exe (即 execute) 執行 set syntax=filetype。execute 用于執行一個表達式字符串,由于未對 filetype 過濾,造成了命令注入。
相關代碼在 /usr/local/share/vim/vim80/syntax/syntax.vim:

patch 8.0.0056 增加了對名稱的校驗。

CVE-2019-12735
最近剛曝出來,影響 Vim < 8.1.1365,Neovim < 0.3.6。和 CVE-2002-1377 原理類似,找到了一個新的繞過沙箱執行命令的點。source 指定的定義如下:

:so! filepath 可以從一個文件加載 vim 命令。

構造 PoC,將待執行的命令放在 text 部分,so! % 加載當前文件。
[text]{white}{vi:|vim:|ex:}[white]{options}

補丁對 source 指令添加了沙箱檢查。

總結
Windows 記事本都任意代碼執行了,Vim 怎么能被比下去 … 漏洞無處不在,謹慎打開任何來歷不明文件。
參考鏈接
https://github.com/numirias/security/blob/master/doc/2019-06-04_ace-vim-neovim.md
https://github.com/vim/vim/commit/d0b5138ba4bccff8a744c99836041ef6322ed39a
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/952/
暫無評論