payload
url => http://127.0.0.1/thinkphp_5.0.10_full/public/index.php?s=index/index/index
post => s=whoami&method=&filter[]=system&_method=__construct
版本:5.0.8~5.0.12
漏洞解析
开始前为了方便大家理解,先大致描述一下被触发的过程。原因在于Request.php文件中reqeust类的属性可控导致自定义filter过滤器可控,而filter又用于过滤用户传入的危害变量,可控的变量被传入了可控的filter中导致漏洞的形成。
从漏洞形成的地方反向跟踪payload的传入过程研究漏洞形成的原因:
首先在request.php的1060行下断点
分析堆栈
可以发现有危害的filter在request.php的1000行的getFilter方法中形成
跟踪进getFilter()方法,过滤器直接由request类的属性filter赋值了
那么$this->filter的属性是什么时候被我们改变的呢,继续在堆栈间查看变量的改变,可以发现属性在App::run()方法调用后和$request->param()方法调用前就已经被改变了。
继续在这两个方法之间一步步的调试,查看filter属性在何处被修改,最后定位到了Route.php第843行,$request调用method()方法后,Request的filter属性被改变。
堆栈如下:
继续查看method方法,在503行时,使用Config::get获取预先定义好的var_method的值"_method",然后把$_POST["_method"]的值__construct赋给method属性,再在504行中使用$this->__construct魔术方法对$_POST进行操作
查看__construct,使用获取的散列为自己的属性赋值,导致了自身属性可被用户操控。
至此整个漏洞的形成原因就明了了。
官方修复
在5.0.13的版本里app.php第544行对$requet>filter进行了默认赋值。