ThinkPHP 5.x路由解析漏洞本质是未启用强制路由时控制器名拼接缺乏校验,导致可调用think\app::invokefunction等敏感方法执行任意代码;修复需启用强制路由、升级至5.0.24+/5.1.31或添加控制器名校验。

ThinkPHP 5.x 路由解析漏洞本质是框架在未启用强制路由时,对URL路径中控制器名和类名的拼接缺乏严格校验,导致攻击者可绕过常规访问逻辑,直接调用框架内部敏感类方法(如 \think\app::invokefunction),最终执行任意PHP代码。该漏洞影响广泛,修复需从配置加固与代码层双重入手。
漏洞触发的核心条件
漏洞生效依赖三个关键配置状态:
-
未开启强制路由:即
'url_route_on' => false或未显式启用路由规则,框架退回到PATH_INFO模式解析 -
控制器名未过滤:URL中控制器段(如
/index/\think\app)被直接拼入命名空间,反斜杠\未转义或拦截 -
存在可利用的反射调用点:如
invokefunction、__construct配合filter参数覆盖等,构成RCE链路
典型攻击路径示例
常见Payload利用方式包括两类主流变体:
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
-
路由参数注入型:
?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id—— 直接触发框架类方法调用 -
method+filter覆盖型(适用于5.0.20–5.0.23):
?s=captcha&_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=1—— 利用Request类初始化时覆盖filter字段,后续param()触发回调
两类利用均依赖于URL参数能抵达框架核心调度逻辑,且中间无有效白名单校验。
推荐修复方案
修复应分层实施,兼顾兼容性与安全性:
-
首选:启用强制路由 —— 在配置中设
'url_route_on' => true,并为所有接口明确定义路由规则,关闭PATH_INFO自动解析能力 -
升级框架版本 —— ThinkPHP 5.0 系列请升至
5.0.24及以上,5.1 系列升至5.1.31,官方已修补App::module和Request::method中的关键逻辑 -
手动补丁(临时应急):在
think\App类的module方法中控制器名赋值后添加校验:
if (!preg_match('/^[A-Za-z][\w.]*$/', $controller)) { throw new HttpException(404, 'controller not exists: ' . $controller); }
开发侧预防建议
避免未来引入同类风险,需在工程实践中落实以下习惯:
- 生产环境始终关闭
app_debug,防止错误信息泄露路径与类结构 - 禁用
url_param_type = 1(顺序解析),改用默认的0(名称成对解析),减少参数歧义 - 控制器类名统一使用驼峰规范,不在URL中暴露真实类路径;敏感操作(如文件写入、命令执行)不暴露在控制器方法中
- 对
input()、param()等接收外部输入的方法,始终指定类型约束(如input('id/d'))并验证业务逻辑边界


















