ThinkPHP 5.0 系列(5.0.0–5.0.24)已终止维护,必须手动加固控制器调用链、HTTP方法伪造、用户输入执行链三类核心入口,否则一条URL即可getshell;补丁不落地则防护无效。

ThinkPHP 5.0 系列漏洞修复不能靠“升级一次就万事大吉”,尤其对 5.0.0–5.0.24 这些已停止官方维护的版本,必须手动加固三类核心入口:控制器调用链、HTTP 方法伪造、用户输入执行链。补丁不落地,攻击者一条 URL 就能写 shell、执行命令、读取日志。
一、封死控制器任意调用漏洞
该漏洞让攻击者绕过路由直接调用 `thinkpp/invokefunction` 等敏感类方法,常见 payload 如 `?s=index/ hinkpp/invokefunction&function=call_user_func_array&vars[0]=system`。
-
修改
thinkphp/library/think/App.php中的module()方法,在解析出$controller后立即加入白名单校验:if (!preg_match('/^[A-Za-z][A-Za-z0-9.]*$/', $controller)) {
throw new HttpException(404, 'controller not exists: ' . $controller);
} 同步关闭自动路由:在
config/app.php中设'auto_route' => false,并确保'url_route_on' => true且'route_complete_match' => true-
入口文件
public/index.php开头添加硬性拦截:if (isset($_GET['s']) && preg_match('/\\think\\|invokefunction|call_user_func/i', $_GET['s'])) {
die('Access Denied');
}
二、堵住 _method 变量覆盖与 RCE 链
5.0.0–5.0.23 中 `Request::method()` 直接将 `$_POST['_method']` 作为方法名调用,配合 `filter[]` 可触发 `system`、`file_put_contents` 等函数。
-
修改
thinkphp/library/think/Request.php的method()方法(约第 500 行):if (isset($_POST[$varMethod])) {
$method = strtoupper($_POST[$varMethod]);
if (!in_array($method, ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'])) {
$this->method = 'POST';
} else {
$this->method = $method;
}
unset($_POST[$varMethod]); // 关键:清除污染源
} 在
config/app.php中显式禁用伪装方法:'var_method' => ''-
拦截高危魔术方法:在入口文件加判断
if (isset($_POST['_method']) && in_array(strtolower($_POST['_method']), ['__construct', '__destruct', '__wakeup', '__toString'])) {
die('Method not allowed');
}
三、阻断 SQL 注入与文件上传风险
5.0.13–5.0.15 的 `parseData()` 导致 `username[0]=exp` 类注入;而上传漏洞本质是业务层缺失校验,非框架缺陷。
-
SQL 注入临时加固(若无法升级至 5.0.16+):
在thinkphp/library/think/db/Builder.php的parseData()函数开头插入:foreach ($data as $key => $val) {
if (is_array($val) && isset($val[0]) && $val[0] === 'exp') {
if (!in_array(strtolower((string)$val[1]), ['count(*)', 'max(id)', 'min(time)'], true)) {
throw new Exception('SQL expression not allowed');
}
}
if (is_string($val) && preg_match('/(select|union|insert|update|delete|drop|load_file|intos+outfile)/i', $val)) {
throw new Exception('Suspicious SQL content detected');
}
} -
文件上传必须做到四重防护:
- 强制重命名:用 uniqid() + mt_rand() 生成文件名,后缀白名单硬编码(如 '.jpg')
- 真实 MIME 校验:用 finfo_file(finfo_open(FILEINFO_MIME_TYPE), $tmp_file),只允许 image/jpeg 等安全类型
- 图片重绘:用 imagecreatefromxxx() → imagejpeg()/imagepng() 丢弃原始元数据和尾部代码
- 上传目录禁执行:Nginx 加 location ~ ^/uploads/.*.php$ { deny all; },Apache 放 `.htaccess` 限制 handler
四、关掉所有调试与日志暴露面
哪怕代码修好了,`APP_DEBUG=true` 或可访问的 `runtime/log/` 目录仍会让攻击者快速定位路径、数据库配置、甚至反推漏洞利用方式。
确保
config/app.php中'app_debug' => false,删除任何独立的extra/debug.php清空
runtime/log/下全部.log文件(含子目录),不要只删空目录-
Nginx 配置中禁止访问敏感路径:
location ~ ^/(runtime|vendor|thinkphp)/ {
deny all;
}
location ~ .(log|php|ini|conf)$ {
deny all;
} 非 Windows 环境下,直接删除
thinkphp/library/think/process/pipes/Windows.php—— 该文件是反序列化 POP 链常用入口,删掉最彻底
所有修改完成后,务必测试以下请求是否返回 403/404:
- ?s=index/ hinkpp/invokefunction&function=system&vars[0]=whoami
- POST /index.php _method=__construct&filter[]=system&get[]=id
- ?s=/index/thinkContainer/invokefunction&function=call_user_func_array
不复杂但容易忽略。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











