CVE-2020-15148 反序列化漏洞复现

CVE-2020-15148 反序列化漏洞复现

起因是在做CTFshow web入门的反序列化题目时碰到了框架的反序列化,就尝试着复现了一下

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

php
'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 表示继承类 例如:

php
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
<?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

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

php
public function __call($method, $attributes)
    {
        return $this->format($method, $attributes);
    }

跟进format方法,发现调用了call_user_func_array方法。call_user_func_array:调用回调函数,并把一个数组参数作为回调函数的参数,这里注意调用对象方法是

php
$obj = new A();
call_user_func_array([$obj, 'method'], []);
php
 public function format($formatter, $arguments = array())
    {
        return call_user_func_array($this->getFormatter($formatter), $arguments);
    }

跟进getFormatter方法。

php
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。

php
public function run()
{
    if ($this->checkAccess) {
        call_user_func($this->checkAccess, $this->id);
    }
    
    return $model;
}

发现checkAccess和id都是可控的,所以整个pop链就出来了。

php
BatchQueryResult->__destruct()
BatchQueryResult->reset()
Generator->close()
Generator->__call()
Generator->format()
Generator->getFormatter()
IndexAction->run()

poc:

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。

CTFShow Web入门 PHP反序列化 Writeup 合集
ThinkPhp5.1 反序列化漏洞复现

评论区

评论加载中...