Thinkphp >= 5.0.23 RCE 分析

发表于 2019 年 1 月 16 日

起因是刚出来那天刚好有个站是 5.0.23 但是分析文章没给完整的截图, 打了码. 干脆自己分析一波写写 poc.

先切换到 v5.0.23

1git clone git@github.com:top-think/framework.git
2git checkout v5.0.23

主要问题出在 library/think/Request.php 中的 method, 其中的 Config::get(‘var_method’) 默认值是 _method, 而其没有任何过滤就被传进 $this->{$this->method}($_POST) 中, 导致可以调用本类的任何单参数函数.

官方的补丁也是增加过滤措施

这里我反着来, 从利用链末端的危险函数 filterValue 开始分析,

可以看到其中调用了 call_user_func, 只要我们能控制 filters 和 value, 就能调用任意函数

这里查找这个方法的引用, 找到 cookie 和 input, 这里我偷懒, 直接加上 echo, 找找看是否有启用

这里可以看到 cookie 方法并未被在框架中直接使用, 所以我们从 input 上下手

可以看到找到一个调用了 input 且 name = '' 的方法就行了, data 将会被作为 filterValue 中的 value.

继续查找引用, 这里我随便找了一个 get, var_dump 了一下确认了 name =''. $_GET 数组将会被当做 value 传进 input.

这样 filterValue 中的 value 已经构造完成, 接下来只要构造 filter 即可, 这个比较简单, 在构造函数中可以看到

只要抢先在底下对 $this->filter 赋值之前给他赋值就行了.

最后需要添加一个 method=GET, 不然没有路由信息

比较遗憾的是, 在比较后面的版本中必须打开 App::debug 或者有 captcha 模块才能利用.

因为有很多地方都调用了 input 方法, 所以 payload 有很多种, 不过本质都是通过类的构造函数来覆盖变量导致 filterValue 被错误的执行.