ThinkPHP 5.0.24反序列化漏洞核心风险在于Windows.php的__destruct触发file_exists进而调用__toString,形成POP链导致RCE;修复需删除Windows.php、禁用APP_DEBUG、屏蔽runtime目录、升级至5.1.31+并禁用php://filter等危险协议。

ThinkPHP 5.0 系统性反序列化漏洞主要集中在 5.0.24 及更早版本,其核心风险在于框架未对反序列化入口做严格限制,且多处类设计存在可控的魔术方法调用链(POP Chain),攻击者可构造恶意 payload 实现任意文件写入、远程命令执行(RCE)甚至服务器权限获取。修复关键不是“打补丁”,而是切断入口 + 限制反序列化触发点 + 升级加固。
典型利用链与危害原理
主流利用链以 think\process\pipes\Windows::__destruct() 为起点:
- 析构时遍历
$this->files并调用file_exists($filename),触发对象的__toString() - 经
Pivot → Model → toArray() → getAttr() → withAttr[closure]链路,最终执行用户可控的闭包函数 - 配合
php://filter流封装器和 base64/rot13 编码,可将恶意 PHP 写入 Web 可访问路径(如public/a.php) - 若环境支持 Memcached 或存在其他 gadget 类,还可绕过 exit 直接执行 RCE
必须关闭的反序列化入口
框架本身不主动反序列化用户输入,但开发者常在控制器中自行添加入口,例如:
-
unserialize($_GET['data'])或unserialize(file_get_contents(...)) - 使用
session_start()后未校验 session 数据完整性,且 session 存储在文件或 Memcached 中 - 自定义缓存驱动、日志处理器等扩展模块中存在反序列化操作
请全局搜索项目中所有 unserialize(、igbinary_unserialize(、msgpack_unpack( 等调用,逐一确认是否接收外部可控输入 —— 只要没做白名单过滤或签名验证,就必须删除或重写。
升级与代码层加固措施
单纯修改单个文件无法根治,需组合实施:
- 强制升级至 ThinkPHP 5.0.24 以上:官方已在 5.0.24 中修复部分反序列化相关逻辑(如 Request 对 method 的校验),但注意:5.0.24 仍存在已知 POP 链,因此推荐直接升级到 5.1.31+ 或迁移到 TP6
-
禁用危险协议流:在
php.ini中设置allow_url_fopen = Off和allow_url_include = Off,并移除php://filter、phar://等协议在open_basedir中的许可 -
限制反序列化类白名单:如必须使用反序列化,改用
json_decode()替代;若不可行,可用unserialize($data, ['allowed_classes' => ['MySafeClass']] )(PHP 7.4+)显式声明允许类 -
重写关键类的魔术方法:对
Windows、Pivot、Model等已知参与链路的类,在生产环境中覆盖其__destruct、__toString方法,直接抛出异常或返回空字符串
验证与监控建议
修复后务必验证有效性:
- 用公开 PoC(如生成
Windows序列化字符串)发起请求,确认返回 500 或 404,而非成功写入文件或执行命令 - 检查 Web 日志中是否存在大量含
unserialize、phar://、php://filter的异常请求 - 在 WAF 或 Nginx 层添加规则拦截含
O:.*?:、s:.*?:".*?";等典型序列化特征的 GET/POST 参数
不复杂但容易忽略

















