Thinkphp5.0.0~5.0.23 RCE漏洞复现分析

Thinkphp5.0.0~5.0.23 RCE漏洞复现分析

image-20211117223456251

漏洞概要

漏洞存在于 ThinkPHP 底层没有对控制器名进行很好的合法性校验,导致在未开启强制路由的情况下,用户可以调用任意类的任意方法,最终导致 远程代码执行漏洞 的产生。

环境搭建:

Phpstudy:

  • OS: Windows
  • PHP: 7.3.4
  • ThinkPHP: 5.0.22

POC

http://xxxxxx.xxx/public/?s=captcha
Body
_method=__construct&filter[]=system&method=get&get[]=whoami
_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=whoami

复现分析

POC 1

image-20211118172356063

调试分析,Thinkphp的程序是从App.php开始的,在App::run中,先通过$dispatch = self::routeCheck($request, $config);对路由进行检测

image-20211118164531151

在该方法中,又调用了Route::check方法,跟进

image-20211118164903693

存在$method = strtolower($request->method());,跟进method方法,进入了Request.php

image-20211118165239755

默认$method = false时进入分支条件

注意到:$this->method = strtoupper($_POST[Config::get('var_method')]);

这里的var_method对应_method,在Config.php

$method来自可控的 $_POST数组,而且在获取之后没有进行任何检查,直接把它作为 Request 类的方法进行调用,同时,该方法传入的参数是可控数据 $_POST 。也就相当于可以随意调用 Request 类的部分方法。

我们传入的参数:_method=__construct&filter[]=system&method=get&get[]=whoami

它会调用__construct方法,而该方法中有类属性覆盖功能

image-20211118174942348

那么在结束method方法时,我们需要返回参数$this->method为get

image-20211118163556291

继续分析

image-20211118225550588

进入了exec方法,?s=captcha就可以让$dispatch['type']是method

在 ThinkPHP5 完整版中,定义了验证码类的路由地址。程序在初始化时,会通过自动类加载机制,将 vendor 目录下的文件加载,这样在 GET 方式中便多了这一条路由。我们便可以利用这一路由地址,使得 $dispatch['type']等于 method ,从而完成 远程代码执行 漏洞。

进入Request::instance()->param()

image-20211118230712251

image-20211118230837911

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

跟进get方法

image-20211118231215186

由于之前的变量覆盖get有值

image-20211118232034784

所以会进入input方法

image-20211118232333297

它返回了get数组值,而$this->param也会有值

image-20211118232755497

接着我们再次进入input方法

image-20211118232920377

进入解析过滤器

image-20211118233244683

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

image-20211118233508379

那么array_walk_recursive($data, [$this, 'filterValue'], $filter);会调用filterValue方法

image-20211118234154433

之后就通过回调函数进行RCE

该调用链的payload:

http://xxxxxx.xxx/public/?s=captcha
POST:
_method=__construct&filter[]=system&method=get&get[]=whoami

POC 2

image-20211119000336365

image-20211118234630188

跟进一下method()方法,这里的$method是true:

image-20211118235037615

继续跟进server方法

image-20211118235123426

这里也有input方法

return $this->server('REQUEST_METHOD') ?: 'GET';

这里的name为REQUEST_METHOD,第一个参数$this->server可以利用之前__construct()方法进行属性覆盖,设置server[REQUEST_METHOD]=whoami,之后会调用到getFilter(),于是分析思路和上一个相似,最终调用回调函数进行RCE

总结

来自一位师傅:

在这里插入图片描述

该复现过程基本是跟着Y4师傅来的,很多地方现在理解也不是很清楚,希望以后能继续完善吧!

继续努力!

                       

点击阅读全文

上一篇 2023年 5月 26日 am10:31
下一篇 2023年 5月 26日 am10:33