大概思路就是我们可以修改requests类的filter属性、method属性以及get属性的值,从而在调用param方法时,call_user_func_array的值我们就可以控制,造成了远程代码执行漏洞。
0. 大致流程
经过入口文件进入run函数
首先在116行根据url获取调度信息时,触发变量覆盖漏洞从而修改requests对象的属性值,然后获取s=captcha的调度信息并返回给$dispatch
再到139行进入exec函数并将$dispatch作为参数带入
跟进后根据$dispatch的type进入到case ‘method’,从而调用requests的param函数,进而造成了rce漏洞
1.环境搭建
这里用的环境是thinkphp5.0.20+php5.6.27+apache+phpstorm
POC:
复现成功
1.1 POC参数解析
method=get 因为captcha的路由规则是get方式下的,所以我们得让method为get,才能获取到captcha的路由
s=captcha 因为在进入exec函数后我们要switch到method中执行param函数,而这个captcha的路由刚好对应类型为method,所以我们选择captcha
filter[]=system 覆盖变量
get[]=whoami 覆盖变量
_method=__construct 为了能够进入construct,从而覆盖变量
2.漏洞分析
这是一个变量覆盖漏洞导致的rce,我们首先来说下变量覆盖漏洞
2.1 变量覆盖漏洞
漏洞触发点在thinkphp/library/think/Request.php的509行:
这里509行的 t h i s − > m e t h o d 我们可控, ∗ ∗ 该值就来自与上一行的 this->method我们可控,**该值就来自与上一行的 this−>method我们可控,∗∗该值就来自与上一行的_POST[Config::get(‘var_method’)],其中Config::get(‘var_method’)的值是_method**
我们post传入_method为__construct,就会调用request对象的构造函数,参数为post内容
跟进__construct,可以看到他将传入的参数依次赋值给相应的属性,这就造成了变量覆盖漏洞,我们可以随便给requests对象的属性赋值,这为后面的rce打下基础。从poc也能看出来,为了能够rce,这里我们需要修改的属性值有filter,get,method,_method
2.2 远程代码执行
RCE的触发点在thinkphp/library/think/Request.php的param函数:
第一个if是获取post的提交内容并赋值给$vars
然后再整合一下赋值给requests对象的param属性
最后调用该类下的input方法,跟进input方法,$data的值为上图红框
public function input($data = [], $name = '', $default =