ThinkPHP 6.0.8存在反序列化POP链RCE和多语言目录穿越+pearcmd RCE两大高危漏洞,修复需同步封禁入口、阻断链路、移除组件:封死所有unserialize()调用并改用json_decode;禁用Redis自动反序列化;物理删除extend/pearcmd目录;拦截think_lang路径穿越请求;禁用php高危函数及phar协议。

ThinkPHP 6.0.8 命令执行过滤失效漏洞,主要指两类高危路径被绕过:一是 **反序列化POP链触发RCE**(如 `Model::__destruct` → `save()` → `eval`/`system` 类调用),二是 **多语言模块目录穿越+pearcmd远程命令执行**(需开启多语言功能)。两者均非单纯“过滤不严”,而是设计逻辑缺陷,修复必须从**入口封禁、链路阻断、组件移除**三方面同步落地。
封死所有反序列化入口点
框架本身不调用 unserialize(),但开发者常在控制器、缓存、日志等位置手动引入风险:
- 全项目执行
grep -r "unserialize(" app/ vendor/ --include="*.php",重点检查$_POST、$_GET['payload']、file_get_contents('php://input')后直接反序列化的代码 - 删除全部显式
unserialize()调用,统一改用json_decode($input, true)传输结构化数据 - 若必须兼容旧协议(如第三方系统对接),强制启用白名单:
$data = @unserialize($input, ['allowed_classes' => ['App\Model\User', 'App\Dto\Config']]);
未命中白名单则直接报错退出
禁用Redis自动反序列化并改造缓存逻辑
think-cache-driver-Redis 的 get() 方法在 serialize=true 时无条件反序列化 Redis 返回值,是攻击链核心入口:
- 修改
config/cache.php中 Redis 配置,将'serialize' => true改为'serialize' => false - 所有写入缓存的数据,统一先
json_encode(),读取时用json_decode($val, true)解析 - 如确需存对象,走两步:先
serialize()→base64_encode()存入;读取后base64_decode()→ 白名单校验 → 再unserialize()
彻底清除pearcmd目录穿越利用面
该漏洞依赖 think_lang 路由 + ../../extend/pearcmd/ 目录穿越,最终加载 pearcmd/index.php 执行 $_GET['cmd']:
- 立即删除项目中
extend/pearcmd/整个目录(非注释、非重命名,必须物理删除) - 检查
config/app.php是否开启多语言:'lang_switch_on' => true。如非必要,设为false - 在入口文件
public/index.php或全局中间件中,拦截含think_lang和双点路径的请求:if (stripos($_SERVER['REQUEST_URI'], 'think_lang') !== false && preg_match('/\.\.\/+/', $_SERVER['REQUEST_URI'])) { http_response_code(403); exit; }
运行时加固与验证
仅改代码不够,还需限制底层能力:
- 在
php.ini中禁用高危函数:disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source - 禁用 Phar 协议(防 phar:// 反序列化):
phar.readonly = On(默认已开,确认未被覆盖) - 升级后,用 PHPGGC 生成
ThinkPHP/RCE1Payload,发送到疑似入口测试响应;同时尝试访问/index.php?s=index/index/index/think_lang/../../extend/pearcmd/,应返回 403 或 404
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











