ThinkPHP5 RCE

栏目: PHP · 发布时间: 6年前

内容简介:主要成因为框架中的核心类 Request 中存在调用任意(其实不能算是任意)方法的点,通过构造可以做成 RCE。这是 ThinkPHP 最近出的第二个影响比较大的 RCE 了,虽然对 ThinkPHP 不熟悉,不过这个洞的成因和利用还是比较有意思的,再加上已经好久没去分析 PHP 方面的漏洞了,写下分析当个记录了。全程是根据别人的分析静态跟代码加上在环境上测试完成的,没有做动态跟踪(懒得去弄了)。5.0 - 5.0.23

主要成因为框架中的核心类 Request 中存在调用任意(其实不能算是任意)方法的点,通过构造可以做成 RCE。

这是 ThinkPHP 最近出的第二个影响比较大的 RCE 了,虽然对 ThinkPHP 不熟悉,不过这个洞的成因和利用还是比较有意思的,再加上已经好久没去分析 PHP 方面的漏洞了,写下分析当个记录了。全程是根据别人的分析静态跟代码加上在环境上测试完成的,没有做动态跟踪(懒得去弄了)。

0x00 影响版本

5.0 - 5.0.23

0x01 漏洞分析及利用构造

进入到漏洞关键点的执行流程:

thinkApp#run --> thinkApp#routeCheck --> thinkRoute#check --> thinkRequest#method

thinkRequest#method 具体代码如下

ThinkPHP5 RCE

在前面的执行流程中调用到 method 方法的时候是不带参数的,所以这里的形参 $method 的实际值为 false,另外 Config::get('var_method') 的值来自于 convention.php 默认为 _method。虽然这里会把字符串变成大写,但是在 PHP 中方法名大小写不敏感,因此在图中的红框处就能实现 Request 中任意方法的调用(当然了得参数类型符合)。

这里选择的类 Request 中的方法为其构造方法,具体代码如下

ThinkPHP5 RCE

选择这个方法主要是为了覆盖类 Request 中的成员变量的值,为后面的利用做准备。

再看 thinkRequest#param

ThinkPHP5 RCE

当 mergeParam 为空时会调用到 get 方法,因为 mergeParam 默认不为空,后面是通过覆盖 mergeParam 的值为空让执行流程如设计好的走下去。但不覆盖它为空往下的流程也差不多,只是在利用的时候控制下边要提到的 value 的方法就不一样了。跟进 thinkRequest#get

ThinkPHP5 RCE

继续跟进 thinkRequest#input

ThinkPHP5 RCE

data 的值来自 Request 中的 get(数组),所以会调用到 array_walk_recursive 函数,而这个函数设置的 callback 函数为 filterValue。漏洞的利用点就在 filterValue 中,其代码如下

ThinkPHP5 RCE

主要就是用 call_user_func 来做成 RCE,因此 filter 和 value 的值需要可控,顺着调用流程往回看和结合前面提到的在构造方法中做覆盖的方法就能知道怎么去控制这两个变量的值。结合前面提到的 value 的值其实就来自于 Request 类中的 get,再来看 filter,很明显能知道 filter 的值来自 getFilter 方法的执行结果,thinkRequest#getFilter

ThinkPHP5 RCE

这个方法的代码逻辑比较简单的,要控制 filter 的值的话,就只需要在 POST 请求中传个 filter 的值就行了。到这里可以知道的了 PoC 中需要构造的请求如下

POST
_method=__construct&mergeParam&=filter=system&get[]=id

接下来只要找到办法调用 thinkRequest#param 就可以完成整个利用了。thinkApp#run 中存在如下代码

ThinkPHP5 RCE

所以要是在开启了调试模式的情况下用前面的构造好的请求就可以完成利用了,但是 23 版本在默认情况下是没有开启调试模式的,再看下在没有开启调试模式的情况下如何利用。

回看 thinkRoute#check 中调用 thinkRequest#method 往后的代码

ThinkPHP5 RCE

这里的 method 的值其实就来自于 Request 类中的 method,因此可控。往下就是根据 method 的值来获取路由规则,这里需要用到验证码类(只在完整版中有,核心版中没有)中的一个路由规则,规则如下

ThinkPHP5 RCE

所以要是想获取到这个路由规则就得传参 s=captcha 来完成类的自动加载同时设置 method 的值为 get。这里获取这个路由规则的主要目的是为了完成漏洞的利用,往下跟就明白了。接下来的执行流程为 thinkRoute#checkRoute --> thinkRoute#checkRule --> thinkRoute#parseRule

parseRule 方法中的部分代码

ThinkPHP5 RCE

这里主要是根据路由规则的格式返回不同的结果,这里返回的结果中 type 为 method。结果返回赋值给 thinkApp 类中的 dispatch。往下跟进 thinkApp#exec

ThinkPHP5 RCE

可以看到这里就能成功调用到了漏洞利用需要的 param 方法。

0x02 PoC

开启调试模式

POST /index.php
_method=__construct&mergeParam&=filter=system&get[]=id

关闭调试模式

POST /index.php?s=captcha
_method=__construct&mergeParam&=filter=system&get[]=id&method=get

另外一种控制 value 的方法

_method=__construct&filter=system&server[REQUEST_METHOD]=id&method=get

0x03 参考


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

PHP and MySQL Web Development

PHP and MySQL Web Development

Luke Welling、Laura Thomson / Sams / July 25, 2007 / $49.99

Book Description PHP and MySQL Web Development teaches you to develop dynamic, secure, commerical Web sites. Using the same accessible, popular teaching style of the three previous editions, this b......一起来看看 《PHP and MySQL Web Development》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具