PHP 7.2反序列化漏洞需代码层加固:堵住不可信输入入口、强制allowed_classes白名单、优先用JSON替代;辅以签名验证与php.ini安全约束。

PHP 7.2 中反序列化漏洞不能靠“版本升级”自动修复,它本质是代码逻辑问题。加固核心就三点:堵住不可信输入入口、限制可反序列化的类、替换或校验序列化数据本身。
识别并清理危险的 unserialize() 入口
所有直接对用户输入调用 unserialize() 的地方都是高危点,必须立即处理。重点检查:
- 从 $_GET、$_POST、$_COOKIE、$_SESSION 或文件读取中获取的字符串是否未经校验就传入 unserialize()
- 第三方 SDK、旧版 CMS 插件、自定义缓存模块里隐藏的反序列化调用(比如某些日志回放、任务队列还原逻辑)
- 使用 preg_replace('/./e') 或 create_function() 等已弃用函数间接触发反序列化的边缘路径
发现后不要简单加个 is_string() 或 strlen() 判断——攻击者构造的恶意 payload 就是合法字符串。应直接删除该调用,或转为白名单校验+JSON 替代方案。
强制启用 allowed_classes 白名单机制
PHP 7.2 已支持 unserialize() 的 allowed_classes 参数,这是最直接有效的缓解手段:
立即学习“PHP免费学习笔记(深入)”;
- 显式传入允许反序列化的类名数组:
unserialize($data, ['allowed_classes' => ['User', 'CartItem']] ) - 若只需反序列化基础类型(数组、字符串、整数等),设为
false:unserialize($data, ['allowed_classes' => false]),此时不会实例化任何对象,仅还原标量和数组 - 禁止使用空数组
[]或不传该参数——这等同于默认开启全部类,风险未变
注意:白名单必须严格对应类的**完整限定名**(如 App\Models\Order),且类必须已加载(建议配合 autoloader 使用,避免 class_exists() 手动判断引入新风险)。
优先用 JSON 替代 serialize/unserialize
绝大多数业务场景中,JSON 不是“替代方案”,而是更安全的默认选择:
- JSON 只能表示数组、字符串、数字、布尔、null,天然无法构造对象、不触发魔术方法、无类型注入风险
- PHP 7.2 的 json_encode() 和 json_decode() 性能已接近 serialize,且支持
JSON_INVALID_UTF8_IGNORE等容错选项 - 改造示例:把
serialize($_SESSION)存 Redis 改为json_encode($_SESSION);读取时用json_decode($raw, true)(true 确保返回关联数组而非对象)
例外情况(如需保留对象行为、继承关系、资源句柄)才考虑保留 serialize,但必须搭配白名单 + 输入签名双重控制。
补充加固:签名验证与环境约束
对确实无法移除反序列化的老系统,追加两层防护:
-
服务端 HMAC 校验:序列化前用密钥生成签名(如
hash_hmac('sha256', $data, $secret)),与数据一同传输;反序列化前先比对签名,不一致直接拒绝 -
php.ini 级别收紧:设置
unserialize_callback_func为空函数(拦截未知类加载)、禁用危险函数(disable_functions = system,exec,passthru,shell_exec,proc_open)、关闭display_errors防止错误信息泄露类名 - 会话处理器若使用
php_serialize(PHP 7.0+ 默认),确认未混用php(旧格式)——格式不一致可能绕过部分校验
不复杂但容易忽略



















