Thinkphp V5.1.x RCE
影响范围:
1 | TP 5.0.7 - 5.0.24 |
环境:
1 | thinkphp5.1.29 + phpstorm |
payload
1 | /?s=index/\think\Request/input&filter[]=system&data=whoami |
分析
1 | 执行调试 |
在index.php中
进入到run() 方法 (App.php)
在这里进行断点, 进行调试

$dispatch = $this->dispatch; 无初始值, 默认为空, 进入到 routeCheck方法
routeCheck方法

跟进到path()方法

继续跟进到pathinfo()方法

$pathinfo获取 当前类的var_pathinfo 的值–>s ,所以可以通过 ?s 参数传入值

根据之前的传参, 此时就已经被赋值为 index/\think\Request/input

继续回到routeCheck方法, 继续向下

到路由检测里面去, 跟进route类的 check()方法
check()方法

经过一系列的检测后会返回一个 UrlDispatch类的对象 —> Url类的对象
继续,返回的对象, 进入到它的init()方法
init()方法

也就是Url类的init()方法
接着进入到parseUrl方法
parseUrl方法

将访问的url的信息拆分为三份 $module $controller $action返回
然后又会实例化一个Module类对象, 访问这个对象的init()方法
Module类对象的init()方法

进过一系列的操作
最后返回的是当前实例化的对象 , 赋值给$dispatch
回到run方法
此时$dispatch是实例化的Module对象


程序继续向下执行

此时$data为null, 又继续执行到Module类的 run()方法
创建一个闭包函数,传入add()方法,然后将闭包函数作为中间件存入$this->queue[$type][] = $middleware;

继续向下执行
进入到dispatch()方法

使用回调函数调用resolve()方法
resolve()

将之前的闭包函数赋值给 $middleware
到下面的call_func_array调用之前的闭包函数

进入到Dispatch类的run()方法

接着向下执行, 又会进入到 exec方法
Module类的exec()方法

接着controller方法

接着parseModuleAndClass方法

关键点:
如果控制器的名字中存在 \或者以\开头,会被会被当作一个类,可以实例化任意类
回到controller方法,会检查类是否存在,存在就会去调用__get()方法

然后是make()方法
make方法用来将类实例化
继续回到exec()方法

获取操作名,就是需要执行的实例化类的方法,然后方法里面对应的参数通过get请求传入
tp的路由规则是 ?s=模块/控制器/操作名
寻找可以利用的类和方法 , 写shell或者执行命令
参考:
https://xz.aliyun.com/t/9361?time__1311=n4%2BxnD0DuAKCqiKi%3DDkDlhjmYemwETh4DvUq%3Dx#toc-3
https://xz.aliyun.com/t/9369?time__1311=n4%2BxnD0DuAKCqiKqD5DsA3o4xgDx90Z0E0poD
