0x01 概述
在本文中,我们研究TYPO3 CMS的核心中的一个关键漏洞,该漏洞通过代码审计挖掘而出。该漏洞使得经过身份验证的用户能够在底层系统上执行任意PHP代码。
受该漏洞影响的版本是TYPO3 8.x到8.7.26,以及TYPO3 9.x到9.5.7。对不可信数据的反序列化会导致远程代码执行漏洞,该漏洞可以与后端中检测到的跨站脚本漏洞(CVE-2019-12748)相结合。
RIP扫描报告(https://demo.ripstech.com/scan/109/165)
0x02 使用payload覆盖数据库
在TYPO3的后端部分保存任何表单时将会发生此漏洞。例如,如果用户修改了pages部分,则可以从TYPO3的SQL数据库中提取要编辑的数据并将其写回数据库。在从数据库获取数据之后,应用逻辑允许通过用户的输入覆盖所获取数据的单列。此特征允许经过身份验证的恶意后端用户覆盖包含序列化数据的数据库值,这些数据稍后会反序列化。这将会导致PHP对象注入,最终攻击者可以远程执行代码(CVE-2019-12747)。
攻击视频(https://blog.ripstech.com/videos/typo3_957.mp4)
0x03 技术细节
在TYPO3中保存后端表单时,将调用$formDataCompiler对象的compile()方法。参数是一个使用用户输入填充的数组,如下第8行所示。
typo3/sysext/backend/Classes/Controller/EditDocumentController.php
<?php
$this->overrideVals = $parsedBody['overrideVals'] ??
$queryParams['overrideVals'] ?? null;
// ...
$formDataCompilerInput['overrideValues'] = $this->overrideVals[$table];
$formData = $formDataCompiler->compile($formDataCompilerInput);
该方法使用for-loop遍历一个有序的FormDataProvider对象列表,并按顺序在每个$provider对象上调用addData()方法。
typo3/sysext/backend/Classes/Form/FormDataGroup/OrderedProviderList.php
<?php
public function compile(array $result): array
{
// ...
foreach ($orderedDataProvider as $providerClassName => $providerConfig) {
// ...
$result = $provider->addData($result);
}
return $result;
}
如上代码的第9行,$provider->addData()的参数$result在下面的addData()方法调用作为其参数。在每次迭代时,变量$result表示数组在$provider处理完其内容后被修改。其中一个providers是DatabaseRecordOverrideValues类的一个实例,该类允许覆盖从数组$result中提取的数据,其中数组的行列值分别为databaseRow和任意key值。
typo3/sysext/backend/Classes/Form/FormDataProvider/DatabaseRecordOverrideValues.php
<?php
public function addData(array $result)
{
foreach ($result['overrideValues'] as $fieldName => $fieldValue) {
if (isset($result['processedTca']['columns'][$fieldName])) {
$result['databaseRow'][$fieldName] = $fieldValue;
// ...
}
}
return $result;
}
最后,下列FormDataProvider对象之一实现了unserialize()方法对被覆盖数据的调用,从而导致漏洞:
typo3/sysext/backend/Classes/Form/FormDataProvider/DatabaseLanguageRows.php
<?php
public function addData(array $result)
{
// ...
if (/*...*/)
{
$result['defaultLanguageDiffRow'][$defaultLanguageKey] = unserialize(
$result['databaseRow'][$result['processedTca']['ctrl']
['transOrigDiffSourceField']]);
这里是有关如何通过工具链expoit PHP对象注入的更多信息的链接: (https://blog.ripstech.com/2018/php-object-injection)
0x04 CVE-2019-12748:在后端的存储型XSS
CMS TYPO3的后端中存在跨站脚本漏洞(CVE-2019-12748)。有权访问Site Redirects部分的非特权用户可以利用t3://伪协议注入一个恶意的URL。
t3://url/?url=javascript:alert(1);
通过添加这个特定的站点,可以重定向另一个拥有更高权限的TYPO3用户,从而诱使他们点击触发恶意JavaScript的链接。攻击者可以将此漏洞作为启动远程代码执行漏洞攻击的支点。
TYPO3会阻止用户利用链接和URL中危险的javascript:伪协议,这意味着TYPO3将直接执行JavaScript。但是,它并不阻止用户利用TYPO3的内置t3://伪协议,该协议实现了多种功能,例如引用TYPO3内部页面,文件,邮件地址或URLs。实际上,指定一个自动转换为可点击链接的URL将绕过TYPO3的白名单,该白名单最初的作用是阻止javascript:伪协议。
0x05 总结
本文所述的漏洞会对具有一个或多个TYPO3后端的用户的TYPO3系统产生严重的影响。经过身份验证并且可以访问Pages部分的后端用户可以在底层远程系统上执行代码。攻击者可以利用Site Redirects模块中的跨站脚本漏洞作为利用此漏洞的支点。
0x06 时间线
- 2019年5月9日:提交漏洞
- 2019年5月9日:漏洞确认
- 2019年5月10日:与厂商安全负责人协调解决问题
- 2019年6月6日:厂商通知6月25号发布补丁
- 2019年6月25日:TYPO3 9.5.8补丁发布
0x07 参考文献
WordPress 5.1 CSRF to Remote Code Execution:
https://blog.ripstech.com/2019/wordpress-csrf-to-rce
Magento 2.3.1: Unauthenticated Stored XSS to RCE:
https://blog.ripstech.com/2019/magento-rce-via-xss
MyBB <= 1.8.20: From Stored XSS to RCE:
https://blog.ripstech.com/2019/mybb-stored-xss-to-rce
WordPress 5.0.0 Remote Code Execution:
https://blog.ripstech.com/2019/wordpress-image-remote-code-execution
CTF Writeup: Complex Drupal POP Chain:
https://blog.ripstech.com/2019/complex-drupal-pop-chain