ThinkPHP 5.1.x~5.2.x全版本 RCE 漏洞分析
2019-01-23 17:19:18

[toc] 大概看了下,这个洞跟5.0的原理大致相同,都是利用Reuqest类的Method方法覆盖了$this->filter属性,然后进入filterValue调用call_user_func($filter, $value)$value当前请求参数和URL地址中的参数合并,从而导致RCE。

漏洞验证

测试版本:Thinkphp_5.1.1 补丁:https://github.com/top-think/framework/commit/2454cebcdb6c12b352ac0acd4a4e6b25b31982e6 需要在入口文件处关闭报错。 图片.png payload

1
c=exec&f=calc.exe&&_method=filter&

图片.png

流程分析

在获取应用调度信息时会调用Request类的method方法获取当前的请求类型 图片.png$this->config->get('var_method')外部可控,即$this->method我们可控,从而我们可以通过$this->{$this->method}($_POST)调用任意方法。 图片.png 图片.png 跟进filter方法,发现我们post的数据可以覆盖$this->filter属性。 图片.png 回到App类,由于我们开启了$this->debug从而可以进入Request类的param方法。 图片.png 跟进param方法,$this->param当前请求参数和URL地址中的参数合并。然后进入input方法。 图片.png 跟进input方法,因为$data为上面提到的$this->param即数组,从而进入if条件执行array_walk_recursive($data, [$this, 'filterValue'], $filter); 图片.png 查阅array_walk_recursive函数可知,该函数会调用$this->filterValue函数,把$data数组的每个值作为其第一个参数,键名作为第二个参数,并且把$this->filter作为第三个参数。 图片.png 继续跟进filterValue方法,发现调用了call_user_func($filter, $value)$filter为刚开始我们覆盖的$this->filter属性的遍历键值,等于$_POST数组。$value当前请求参数和URL地址中的参数合并数组$this->param的键值。 图片.png 当遍历到$this->param的第二个键值calc.exe$filters的第一个键值exec时,成功执行命令,弹出了计算器。 图片.png

补丁分析

图片.png 与5.0一样,对表单请求类型伪装变量添加了白名单。