最有效方法是直接禁用 unserialize() 调用点;需替换为 json_decode()、启用 allowed_classes 白名单、禁用 Phar 协议、升级至 ThinkPHP 6.3+ 并禁用不安全驱动。

直接禁用 unserialize() 的调用点最有效
ThinkPHP 中反序列化漏洞的根源,几乎都来自开发者或框架自身在不可信上下文中调用了 unserialize()。比如 $_GET['data']、缓存文件读取、日志反解、Session 解析等场景。只要输入可控且未校验,POP 链就可能被触发。修复的第一步不是“加固链”,而是砍掉入口。
常见高危位置包括:
-
think\cache\driver\File->read():读取缓存文件时直接unserialize($content) -
think\session\driver\Memcache->read()或Redis->read():若 session 数据被污染,反序列化即触发 - 自定义控制器中显式调用
unserialize($_GET['payload'])(尤其在调试/旧代码中)
建议全部替换为 json_decode($data, true),并确保数据来源可信。JSON 不会还原对象,天然规避魔术方法调用。
强制启用 allowed_classes 参数
PHP 7.4+ 支持 unserialize() 的第二个参数 allowed_classes,它能白名单制限制可还原的类名。这是目前最轻量、最有效的兜底手段。
立即学习“PHP免费学习笔记(深入)”;
错误写法:unserialize($input)
正确写法:unserialize($input, ['allowed_classes' => ['think\Cache', 'think\helper\Arr']]')
注意点:
- 传
false表示禁止任何类(只允许数组/标量),但需确认业务逻辑不依赖反序列化对象 - 空数组
[]和['__PHP_Incomplete_Class']等同于不设限,毫无防护作用 - ThinkPHP 自身组件如
think\Model、think\Request绝对不能放进白名单——它们是 POP 链主力输出类
禁用 Phar 协议与危险流封装器
Phar 反序列化是 ThinkPHP 漏洞利用的高频路径,尤其当攻击者通过 phar://xxx.jpg/exploit.phar 触发时,file_exists()、file_get_contents() 等函数会自动反序列化元数据。
必须在 php.ini 中关闭:
-
phar.readonly = Off→ 改为On(默认值,但部分旧环境会手动关) -
allow_url_include = On→ 必须设为Off -
stream_wrapper_register不应被用户代码调用;检查是否有自定义协议注册(如filter://、data://)
线上环境还建议在 Web 服务器层拦截 phar:// 请求,例如 Nginx 中添加:if ($request_uri ~* "phar://") { return 403; }
升级到 ThinkPHP 6.3+ 并禁用不安全驱动
ThinkPHP 5.x 全系(5.0.x–5.1.x)均存在已知反序列化链,且官方已停止维护。6.0–6.2 虽修复部分链,但仍存在绕过风险(如 CVE-2024-44902)。真正稳定的版本是 6.3+,它移除了 think\process\pipes\Windows 等高危类,并重构了缓存与 Session 驱动。
迁移时务必检查:
- 禁用
File缓存驱动(易受损坏/篡改),改用Redis或Memcached,并确保连接密码认证开启 - 废弃所有基于
__destruct/__toString的自定义日志、输出、模型扩展类 - 删除项目中残留的
think\console\Output、think\Model子类滥用逻辑(如重写toArray()调用call_user_func)
最后提醒:哪怕用了 allowed_classes 和 PHP 8.1+,只要业务里还留着一个 unserialize($_POST['raw']),整个防御就形同虚设。真正的修复,永远始于删掉那行危险调用。



















