作者:Ricter Z@360高級攻防實驗室
原文鏈接:http://noahblog.#/tex-restricted-mode-bypass/
漏洞時間線:
- 2021/03/08 - 提交漏洞至 TeX 官方;
- 2021/03/27 - 漏洞修復,安全版本:TeX Live 2021;
- 2021/06/06 - 漏洞分析公開。
I. Tex 安全限制概述
TeX 提供了 \write18 原語以執行命令。為了提高安全性,TexLive 的配置文件(texmf.cnf)提供了配置項(shell_escape、shell_escape_commands)去配置 \write18 能否執行命令以及允許執行的命令列表。
其中 shell_escape 有三種配置值,分別為:
- f:不允許執行任何命令
- t:允許執行任何命令
- p:支持執行白名單內的命令(默認)
白名單命令列表可以通過如下命令查詢:
kpsewhich --var-value shell_escape_commands
shell_escape 配置值可以通過如下命令查詢:
kpsewhich --var-value shell_escape
本文涉及的 CVE 如下:沒 advisory 懶得申請了。
II. 挖掘思路
TeX 提供了一個默認的白名單命令列表,如若在調用過程中,這些命令出現安全問題,則會導致 TeX 本身在調用命令的時候出現相同的安全問題。
可以假設:在命令調用的過程中,由于開發者對于命令參數的不完全掌握,有可能存在某個命令參數最終會作為系統命令進行調用的情況。依據這個思路,挖掘白名單內的命令以及白名單內命令的內部調用,并最終得到一個調用鏈以及相關的參數列表,依據研究人員的經驗去判斷是否存在安全問題。
III. 在 *nix 下的利用方式
通過針對命令的深入挖掘,發現白名單內的 repstopdf 命令存在安全問題,通過精心構造參數可以執行任意系統命令。
repstopdf 意為 restricted epstopdf,epstopdf 是一個 Perl 開發的腳本程序,可以將 eps 文件轉化為 pdf 文件。repstopdf 強制開啟了 epstopdf 的 --safer 參數,同時禁用了 --gsopt/--gsopts/--gscmd 等 GhostScript 相關的危險參數,以防止在 TeX 中調用此命令出現安全問題。repstopdf 調用方式如下:
repstopdf [options] [epsfile [pdffile.pdf]]
repstopdf 會調用 GhostScript 去生成 pdf 文件(具體調用參數可以用過 strace 命令進行跟蹤),其中傳入的 epsfile 參數會成為 GhostScript 的 -sOutputFile= 選項的參數。
通過查閱 GhostScript 的文檔可知,GhostScript 的此項參數支持管道操作。當我們傳入文件名為:|id 時,GhostScript 會執行 id 命令。于是我們可以構造 repstopdf 的參數實現任意的命令執行操作,不受前文所提及的限制條件限制。利用方式如下所示:
repstopdf '|id #'
在 TeX 內的利用方式為:
\write18{repstopdf "|id #"}
IV. 在 Windows 下的利用方式
Windows 平臺下,白名單內存在的是 epstopdf 而非 repstopdf,且相關參數選項與 *nix 平臺下不相同,但仍舊存在 --gsopt 選項。利用此選項可以控制調用 GhostScript 時的參數。
此參數只支持設定調用 GhostScript 時的參數選項。參考 GhostScript 的文檔,指定參數 -sOutputFile 及其他相關參數即可。利用方式為:
epstopdf 1.tex "--gsopt=-sOutputFile=%pipe%calc" "--gsopt=-sDEVICE=pdfwrite" "--gsopt=-"
V. LuaLaTeX 的安全問題
LuaLaTex 內置了 Lua 解釋器,可以在編譯時執行 Lua 代碼,原語為:\directlua。LuaLaTeX 支持調用系統命令,但是同樣地受到 shell_escape 的限制。如在受限(f)模式下,不允許執行任意命令;默認情況下只允許執行白名單內的命令。由于可以調用白名單內的命令,LuaLaTeX 同樣可以利用 III、IV 內描述的方式進行利用,在此不做進一步贅述。
LuaLaTeX 的 Lua 解釋器支持如下風險功能:
- 命令執行(io.popen 等函數)
- 文件操作(lfs 庫函數)
- 環境變量設置(os.setenv)
- 內置了部分自研庫(fontloader)
1. 環境變量劫持導致命令執行
通過修改 PATH 環境變量,可以達到劫持白名單內命令的效果。PATH 環境變量指定了可執行文件所在位置的目錄路徑,當在終端或者命令行輸入命令時,系統會依次查找 PATH 變量中指定的目錄路徑,如果該命令存在與目錄中,則執行此命令(https://en.wikipedia.org/wiki/PATH_(variable))。
將 PATH 變量修改為攻擊者可控的目錄,并在該目錄下創建與白名單內命令同名的惡意二進制文件后,攻擊者通過正常系統功能調用白名單內的命令后,可以達到任意命令執行的效果。
2. fontloader 庫安全問題
fontloader 庫存在典型的命令注入問題,問題代碼如下:
// texk/web2c/luatexdir/luafontloader/fontforge/fontforge/splinefont.c
char *Decompress(char *name, int compression) {
char *dir = getenv("TMPDIR");
char buf[1500];
char *tmpfile;
if ( dir==NULL ) dir = P_tmpdir;
tmpfile = galloc(strlen(dir)+strlen(GFileNameTail(name))+2);
strcpy(tmpfile,dir);
strcat(tmpfile,"/");
strcat(tmpfile,GFileNameTail(name));
*strrchr(tmpfile,'.') = '\0';
#if defined( _NO_SNPRINTF ) || defined( __VMS )
sprintf( buf, "%s < %s > %s", compressors[compression].decomp, name, tmpfile );
#else
snprintf( buf, sizeof(buf), "%s < %s > %s", compressors[compression].decomp, name, tmpfile );
#endif
if ( system(buf)==0 )
return( tmpfile );
free(tmpfile);
return( NULL );
}
12345678910111213141516171819202122
調用鏈為:
ff_open -> ReadSplineFont -> _ReadSplineFont -> Decompress -> system
通過 Lua 調用 fontloader.open 函數即可觸發。此方式可以在受限(f)模式下執行命令。
VI. DVI 的安全問題
DVI(Device independent file)是一種二進制文件格式,可以由 TeX 生成。在 TeX 中,可以利用 \special 原語嵌入圖形。TeX 內置了 DVI 查看器,其中 *nix 平臺下為 xdvi 命令,Windows 平臺下通常為 YAP(Yet Another Previewer)。
1. xdvi 命令的安全問題
xdvi 在處理超鏈接時,調用了系統命令啟動新的 xdvi,存在典型的命令注入問題。問題代碼如下:
// texk/xdvik/hypertex.c
void
launch_xdvi(const char *filename, const char *anchor_name)
{
#define ARG_LEN 32
int i = 0;
const char *argv[ARG_LEN];
char *shrink_arg = NULL;
ASSERT(filename != NULL, "filename argument to launch_xdvi() mustn't be NULL");
argv[i++] = kpse_invocation_name;
argv[i++] = "-name";
argv[i++] = "xdvi";
/* start the new instance with the same debug flags as the current instance */
if (globals.debug != 0) {
argv[i++] = "-debug";
argv[i++] = resource.debug_arg;
}
if (anchor_name != NULL) {
argv[i++] = "-anchorposition";
argv[i++] = anchor_name;
}
argv[i++] = "-s";
shrink_arg = XMALLOC(shrink_arg, LENGTH_OF_INT + 1);
sprintf(shrink_arg, "%d", currwin.shrinkfactor);
argv[i++] = shrink_arg;
argv[i++] = filename; /* FIXME */
argv[i++] = NULL;
...
execvp(argv[0], (char **)argv);
1234567891011121314151617181920212223242526272829303132333435363738
2. YAP 安全問題
YAP 在處理 DVI 內置的 PostScripts 腳本時調用了 GhostScript,且未開啟安全模式(-dSAFER),可以直接利用內嵌的 GhostScript 進行命令執行。
VII. 漏洞利用
TeX 底層出現安全問題時,可以影響基于 TeX 的相關在線平臺、TeX 編輯器以及命令行。下面以 MacOS 下比較知名的 Texpad 進行演示:

VIII. 參考文章
- http://scumjr.github.io/2016/11/28/pwning-coworkers-thanks-to-latex/
- https://mirrors.tuna.tsinghua.edu.cn/CTAN/support/epstopdf/epstopdf.man1.pdf
- https://www.texfaq.org/FAQ-spawnprog
- https://0day.work/hacking-with-latex/
- https://www.ghostscript.com/doc/current/Use.htm#Pipes
- https://ruxcon.org.au/assets/2017/slides/hong-ps-and-gs-ruxcon2017.pdf
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1596/
暫無評論