thinkphp5 Request 远程代码执行漏洞分析

影响版本

根据thinkphp发布的5.0.24的补丁可以看到问题出在核心类Request的method方法。补丁增加了对传入的$method的限制。

1
2
3
漏洞影响的产品版本包括:

ThinkPHP 5.0.x ~ 5.0.23

漏洞分析

本文以5.0.5 full版本进行分析


这里Config::get(‘var_method’)获取到的内容为_method,被称为表单请求类型伪装变量,具体功能不细究,可查阅官方文档了解。

那么在未打补丁之前对POST进来的_method变量未作任何过滤,而且下面直接进行了调用,而且函数参数可控。那么便可实现对本类所有方法的调用。

1
$this->($this->method)($_POST);

根据payload,其传入的是_method = __construct
查看__construct方法

该方法对传入的参数数组进行遍历,并通过property_exists检查对象或类是否具有该属性。如果是本类的属性,则通过$this->$name = $item对属性进行重新赋值。
那么这里因为传入的参数可控,可实现对Requset类下任意属性的覆盖。

单单一个变量覆盖是不能得到满足的,继续将这个漏洞扩大化。
可以查看可以覆盖的属性,并看看这些属性的覆盖会不会引起更致命的操作。
这是其中一部分属性

而通过已知的payload了解到这里的全局过滤规则filter被覆盖。查看哪里用到了filter,搜索后发现该类中很多方法都用到了这个变量

其中input方法中调用了filterValue方法

而filterValue方法中,将其带入了call_user_func函数,这里还有一个参数value,向上跟踪value来自于input方法的data,继续往上查看到哪里调用了input。发现了param方法,data来自于其$this->param

1
2
// 当前请求参数和URL地址中的参数合并
$this->param = array_merge($this->get(false), $vars, $this->route(false));

其中$vars数组来自上面,也即我们通过http传入的参数

到此为止,call_user_func的两个变量我们均可以控制,便可以实现任意代码执行。

其中这里要想任意代码执行有两个条件:

  • 1.调用method()实现filter变量覆盖
  • 2.调用param()方法,实现任意代码执行链

首先是第一条在检测url路由check()中触发

整个调用链运行时自动加载

而第二个条件。全局搜索漏洞触发点,看看哪里调用了param方法。
其中当开启debug时调用param。

当debug关闭时,继续搜索其他触发点。

这里当dispatch[‘type’]==’method’时,触发param方法
向上跟踪dispatch

最终还是与$request->method()有关

而method方法返回的method是可以覆盖掉的,可以post传递method=get控制dispatch的最终值,从而进入method分支,调用param

0x02 payload

最终payload

1
2
3
post:

_method=__construct&method=get&filter=system&boo=whoami

本文标题:thinkphp5 Request 远程代码执行漏洞分析

文章作者:boogle

发布时间:2019年01月28日 - 22:58

最后更新:2019年03月07日 - 11:38

原始链接:https://zhengbao.wang/thinkphp5-Request-远程代码执行漏洞分析/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

感觉写的不错,给买个棒棒糖呗