PHP 8.1 反序列化防护需配置加固与编码规范并重:强制使用 allowed_classes 白名单、禁用 phar 协议、隔离会话/缓存序列化数据、封装 unserialize 并添加日志监控。

PHP 8.1 中反序列化漏洞的防御不能只靠版本升级,关键在于配置加固与编码规范双管齐下。8.1 虽默认禁用部分危险函数(如 unserialize 对 __wakeup 的调用限制增强),但若业务仍需使用反序列化,就必须主动启用白名单机制并关闭隐式触发路径。
启用 allowed_classes 白名单(强制项)
PHP 8.1 要求 unserialize() 必须显式指定 allowed_classes 参数,否则抛出 E_WARNING 并返回 false。这是最直接有效的第一道防线:
- 只允许反序列化明确信任的类,例如:
unserialize($data, ['allowed_classes' => ['User', 'Order']]) - 禁止使用
true或空数组,['allowed_classes' => true]等同于开放全部类,等同于未设防 - 若只需反序列化数组/基本类型,应传入
['allowed_classes' => false],此时仅支持非对象数据
禁用危险协议与扩展配置
Phar 文件利用是 PHP 反序列化高危入口,8.1 默认仍启用 phar 协议,需手动关闭:
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
- 在
php.ini中设置:phar.readonly = On(默认已是 On,确认不可改写) - 禁用
phar协议解析:stream_wrapper_unregister('phar')(建议在应用启动时执行) - 检查并移除不必要的扩展,如
curl、gd若无图像/网络需求,可减少 POP 链可用跳板
会话与缓存层隔离策略
Session 和 Redis/Memcached 中存储的序列化数据极易成为攻击跳板:
立即学习“PHP免费学习笔记(深入)”;
- 将
session.serialize_handler改为php_serialize(非默认的php),避免旧格式兼容导致的解析歧义 - 禁止在 session 数据中存储用户可控对象;敏感字段一律转为 JSON 存储(
json_encode/json_decode) - Redis 缓存中若必须存对象,先用
base64_encode(serialize(...))+ 白名单校验,读取时严格验证类名前缀
运行时 Hook 与日志监控
主动感知异常反序列化行为,便于快速响应:
- 通过
set_error_handler()捕获unserialize()失败警告,记录来源 IP、参数片段、调用栈 - 对所有
unserialize()调用点统一封装,加入审计日志和速率限制(如每分钟最多 5 次) - 启用 PHP 8.1 的
opcache.preload预加载可信类定义,配合opcache.validate_timestamps=0提升白名单校验性能


















