ThinkPHP漏洞挖掘需先确认版本与入口点:通过路由特征(如/s=)、文件路径(/thinkphp/library/think/Request.php)、FOFA语句等精准识别版本;紧盯s、_method、server[REQUEST_METHOD]等关键参数,结合框架解析逻辑与真实环境限制(WAF、disable_functions、Nginx配置)开展审计。

ThinkPHP漏洞挖掘不是靠猜,而是有明确路径可循:先确认版本和入口点,再结合框架机制找可控参数,最后验证是否能突破沙箱或触发危险函数调用。
怎么快速确定ThinkPHP版本和关键入口
版本决定可用的漏洞面,入口点决定利用链起点。别依赖响应头或报错信息——它们常被删减或屏蔽。
- 访问
/index.php?s=/或/index.php?s=index/index/index,观察是否返回“无法加载模块”或“控制器不存在”,这是5.x默认路由机制的典型特征 - 尝试
/index.php?m=1&c=2&a=3,若返回空白或“非法模块”,说明启用了兼容模式(常见于老版本或定制部署) - 请求
/public/static/或/thinkphp/library/think/Request.php(注意大小写),部分未清理的开发环境会直接暴露文件,从中可提取版本号注释或类定义特征 - FOFA语句
body="thinkphp" && title!="404"比单纯搜body="ThinkPHP"更准,能过滤掉大量误报的静态页面
哪些参数最值得盯住——不是所有GET/POST都平等
ThinkPHP对不同来源参数的处理逻辑差异极大。攻击面不在“用户输入多”,而在“框架如何解析并使用它”。
-
s参数(如?s=index/test/hello)是路由主入口,5.0.x中它会参与模块/控制器/方法三级解析,且点号.会被转换为目录分隔符,导致?s=index/\x2e\test\hello可能绕过白名单校验 -
_method参数在5.0.x中是Request类的后门开关,配合filter[]可覆盖Request::$filter,让后续input()调用走assert或system -
server[REQUEST_METHOD]这类嵌套数组参数,在5.0.22之前不会被严格过滤,可被用于覆盖$_SERVER变量,进而影响method()等内部判断逻辑 - 模板渲染上下文中的
{\$var}或{:func($arg)},如果$var来自input('get.')且未禁用函数调用标签,则存在模板注入风险
为什么有些payload在本地复现成功,打真实站点却失效
真实环境的WAF、PHP配置、框架补丁、甚至Nginx重写规则,都会截断或变形你的请求。不能只看EXP能不能跑,要看中间哪一环断了。
立即学习“PHP免费学习笔记(深入)”;
- PHP禁用函数列表(
disable_functions)里如果写了system,exec,passthru,shell_exec,proc_open,那所有基于命令执行的payload都会静默失败——改用file_put_contents写shell或phpinfo()探测环境更稳妥 - Nginx配置了
location ~ \.php$但没加fastcgi_split_path_info,会导致/index.php/xxx这种路径被当成静态文件,s参数根本进不到PHP层 - 某些运维把
vendor/目录移出webroot,但忘了删composer.json,此时/composer.json可读,能反推框架版本和组件依赖,比盲打更高效 - ThinkPHP 5.1.31+修复了
_method=__construct路径,但如果你发现__call或__invoke在某个类里被不当暴露(比如日志门面Log::),POP链可能依然成立
真正卡住人的往往不是原理不懂,而是没意识到s参数在Nginx+PHP-FPM下可能被截断,或者_method在5.0.23之后只是换了个地方藏——得去翻Request.php里mergeParam和input的调用顺序。



















