原理介绍
在 PHP 中 ${} 是可以构造一个变量的,{}写的一般字符可以等价被看作变量,例如 ${a} == $a
thinkphp 中所有的主入口文件默认访问index控制器(模块)
thinkphp 中 所有的控制器默认执行index动作(方法)
例如
http://ExampleSever/index.php?s=/模块/控制器/操作/[参数名/参数值...]
数组$var在路径存在模块和动作时,会去除前面2个值(模块和控制器),保留操作。数组 $var 来自 xplode($depr,trim($_SERVER['PATH_INFO'],'/')); 也就是路径当中。
因此我们可以构造出如下POC
/index.php?s=a/b/c/${phpinfo()} /index.php?s=a/b/c/${phpinfo()}/c/d/e/f /index.php?s=a/b/c/d/e/${phpinfo()} ...
在 thinkphp 中存在一个 Dispatcher.class.php 主要负责解析路由。在该文件中存在一个函数名为 static public function dispatch() 这是URL映射控制器,主要是为了将URL访问路径映射到该控制器下获取资源。当我们输入的URL作为变量传入的时候,该URL映射将会把变量以数组的方式提取出来,从而导致漏洞的产生。
Dispatcher, class Dispatcher extends Think 中的方法: static public function dispatch() URL映射到控制器 public static function getPathInfo() 获得服务器的PATH_INFO信息 static public function routerCheck() 路由检测 static private function parseUrl($route) static private function getModule($var) 获得实际的模块名称 static private function getGroup($var) 获得实际的分组名称
复现