ThinkPHP5核心类Request远程代码执行漏洞分析
漏洞概述
2019年1月11日,ThinkPHP团队发布补丁修复了一处由于不安全的动态函数调用导致的远程代码执行漏洞。该漏洞危害程度非常高,默认条件下即可执行远程代码。
受影响版本:ThinkPHP5.0-5.0.23完整版
漏洞复现环境
- ThinkPHP 5.0.22完整版
- PHP 5.5.38
- Apache
漏洞分析
关键漏洞点
漏洞关键点位于:thinkphp/library/think/Request.php:518
在method函数的第二个if分支中,引入了外部可控的数据$_POST[Config::get('var_method')],而var_method的值为_method。
攻击流程
-
构造函数覆盖:攻击者可以通过控制
$options参数来覆盖Request类的filter属性、method属性以及get属性的值。 -
param函数调用:在Request类的
param函数中,当$this->mergeParam为空时,会调用$this->get(false)。 -
input函数调用:
$this->get函数末尾调用了$this->input函数,并将可控的$this->get传入。 -
过滤器获取:
$this->input函数调用$this->getFilter取得过滤器,其中$this->filter的值是攻击者可控的。 -
代码执行:在
filterValue函数中,call_user_func函数的$filter和$value参数都是可控的,导致代码执行。
完整利用链
-
入口点:
thinkphp/library/think/App.php:77的run函数实例化Request类。 -
路由检测:调用
routeCheck($request,$config),进而调用Route::check进行路由检测。 -
变量覆盖:通过
method函数覆盖$this->filter、$this->method、$this->get属性。 -
路由规则:完整版比核心版多出的
think-captcha/src/helper.php文件会调用\think\Route::get进行路由注册,改变self::$rules的值。 -
路由解析:当攻击者控制
$method为get时,$rules的值就是captcha路由的规则,最终调用到self::parseRule函数。 -
命令执行:最终调用Request类的
param方法,完成利用链。
版本差异
- ThinkPHP5.0.2-5.0.23:可以使用同一个POC
- ThinkPHP5.0-5.0.1:需要更改POC,因为
Route.php的rule函数中对$type的处理不同(5.0-5.0.1转换为大写,5.0.2-5.0.23转换为小写)
补丁分析
在ThinkPHP5.0.24中,增加了对$this->method的判断,不再允许自由调用类函数。
安全建议
- 升级版本:强烈建议用户升级到ThinkPHP5.0.24或更高版本
- 关闭debug模式:避免遭受攻击
- 输入过滤:对所有用户输入进行严格过滤和验证
- 最小权限原则:运行环境使用最小必要权限
技术总结
该漏洞本质上是由于ThinkPHP框架中Request类对用户输入处理不当,导致攻击者可以控制函数调用和参数,最终实现远程代码执行。完整版特有的captcha路由组件为攻击提供了必要的路由规则,这也是核心版不受影响的原因。