PHP 7.2.30 不支持 unserialize() 的 allowed_classes 参数,无法通过白名单加固,必须将所有外部输入的 unserialize() 替换为 json_decode($data, true) 并严格校验字段与类型。

PHP 7.2.30 不支持 unserialize() 的 allowed_classes 参数(该特性从 PHP 7.4 才引入),所以**不能靠加白名单来“加固” unserialize**——这条路在 7.2 下根本走不通。唯一可靠的做法是:把所有外部输入的反序列化逻辑,替换成 json_decode($data, true),并配套做字段校验与类型约束。
哪些地方必须改?盯紧外部数据入口
重点排查以下位置是否用 unserialize() 处理用户可控数据:
-
$_GET、$_POST、$_COOKIE中的字段(如$_COOKIE['user_prefs']) - 缓存读取:比如
file_get_contents(cache_file)后直接unserialize() - Session 解析逻辑(尤其自定义 session handler)
- 日志回放、调试接口、导入文件解析等低权限可触达路径
替换为 json_decode 的实操要点
不是简单换函数名,要保证行为安全且兼容:
- 始终传第二个参数
true,确保返回关联数组而非对象,避免后续误调魔术方法 - 设置合理
$depth(如16),防深度嵌套攻击;PHP 7.2 支持json_decode($json, true, 16) - 检查返回值是否为
null,并用json_last_error()判定失败原因(如格式错误、超深、UTF-8 问题) - 禁止 fallback:一旦
json_decode失败,绝不退回到unserialize()—— 这是常见后门漏洞点
字段与类型必须显式校验
JSON 本身不保业务语义,需补上层校验:
- 限定允许字段名(如只接受
['nickname', 'theme', 'notify']) - 逐字段检查类型:
is_string($data['nickname'])、is_bool($data['notify']) - 字符串长度限制(如
mb_strlen($data['nickname']) ) - 枚举值校验(如
in_array($data['theme'], ['light', 'dark', 'auto']))
旧数据怎么过渡?离线迁移 + 默认兜底
数据库或缓存里可能存着老的 serialize() 字符串,不能在线强转:
- 写一个一次性迁移脚本,读出旧数据 →
unserialize()→ 转成 JSON → 写回,仅限运维执行 - 线上代码中,对无法解析的输入,返回默认配置(如空数组或预设值),不报错也不降级
- 记录解析失败日志,用于识别残留旧格式,但日志内容须脱敏(不记原始 payload)
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











