1 影响范围
ThinkPHP 5.0.5 - 5.0.22
2 实验环境
ThinkPHP 5.0.12
php 5.6.27
3 漏洞分析
漏洞主要成因是对Request对象的构造方法进行调用,然后实现成员属性的覆盖
POST传入:_method=__construct&method=GET&filter[]=system&s=whoami
3.1 变量覆盖
一直跟进至method(),调用栈如下:var_method
默认值为_method
代码向下跟进,通过POST传入_method
参数,即会进入到红框内的条件中,通过控制_method及$_POST数组即可实现对Request类的任意方法进行调用
这里传入的_method为构造函数__construct,跟进到当前类的构造函数,在红框内通过foreach对当前对象已经定义的属性值进行覆盖。这里覆盖了filter,此值为用于全局过滤的函数
最后得到的值为:
$this
method = "GET"
filter = {array}[1]
0 = "system"
input = "_method=__construct&method=GET&filter%5B%5D=system&s=whoami"
这部分变量覆盖就结束了
3.2 代码执行
跟进第一部分的解析可知,最后会在input()中使用filter对参数进行处理,所以这半部分最主要是跟进到input()
然后回到thinkApp::run(),进入exec()
然后进入module()
然后再进入invokeMethod()
然后再进入bindParams()
然后再跟进到param()
这里我们请求的方式为POST,但是在POST条件中$vars = $this->post(false);进入post()后再进入的input()方法会直接返回,所以这里不直接跟进到param()最终返回的input()中
进入input(),首先是获取过滤器
进入getFilter(),默认传入filter为'',所以这里取Request对象下的filter,这里即为前面覆盖的值
继续回到input(),在继续跟进到array_walk_recursive()
然后会进入到filterValue(),这里面会对提交的参数值进行过滤,通过call_user_func执行代码
3.3 其他
网上部分payload使用的index.php?s=captcha
,这个在\vendor\topthink\think-captcha\src\helper.php
下注册了路由
使用的请求方式为GET,所以在传参时会传入method=GET
,上面分析的那个payload可以不传入
评论已关闭