PHP 8.0.25 已停止官方维护且存在未修复的反序列化高危风险,严禁用于生产环境;必须严格禁止用户可控数据进入 unserialize(),优先用 json_decode() 替代,或改用 Serializable 接口+白名单校验,并配合 php.ini 与 Web 服务器层防护。

PHP 8.0.25 已停止官方维护,且存在多个未修复的反序列化相关风险(如 CVE-2021-21708 衍生利用链、__wakeup 绕过缺陷等),**不应继续用于生产环境**。若因历史原因暂未升级,需从代码层严格约束魔术方法行为,而非依赖版本自带“安全性”。
明确禁止用户可控数据进入反序列化流程
这是最根本的防线。任何来自 GET/POST/COOKIE/HTTP 头、文件上传、数据库读取、缓存反取的数据,只要未经强类型校验与白名单过滤,一律不得传入 unserialize()。
- 用
json_decode()替代unserialize()—— JSON 不支持对象、资源、闭包,天然规避 POP 链触发 - 必须保留序列化格式时,改用
igbinary或msgpack并禁用原生unserialize全局调用 - 在 autoloader 或入口处加钩子,拦截含
O:、C:、R:等 PHP 序列化特征的字符串,直接拒绝解析
对已存在的 __wakeup / __destruct 做最小化加固
这两个方法最容易被攻击者利用为“自动执行跳板”。即使类本身无害,属性若被控制,就可能引发链式调用。
-
__wakeup()中避免使用$this->xxx做文件操作、SQL 拼接、回调调用;优先设为final并留空体 -
__destruct()内禁止访问任何用户输入属性;若必须清理资源,先校验属性类型(如is_string($this->file))并限定路径白名单(如str_starts_with($this->file, '/tmp/')) - 所有可被反序列化的类,显式声明
private $allowed_props = ['id', 'name'];,并在__wakeup中 unset 非法属性
启用 Serializable 接口替代原生序列化
当业务确实需要自定义序列化逻辑,应弃用 __sleep/__wakeup,改用 Serializable 接口,完全掌控序列化内容。
- 实现
serialize()方法时,只返回经过array_filter和array_keys白名单筛选后的属性键值对 -
unserialize($data)方法中,强制将$data解析为数组,并逐项校验键名与值类型,非法字段直接忽略或抛出异常 - 注意:PHP 8.1+ 已废弃
Serializable,但 8.0.25 仍支持,是当前环境下更可控的选择
运行时层面补位:禁用危险配置 + 日志审计
代码加固之外,需配合运行时限制降低攻击面。
-
php.ini 中设置
unserialize_callback_func=assert(不推荐)或更安全的unserialize_callback_func=custom_unserialize_handler,并在该函数中记录所有尝试反序列化的类名并告警 - 关闭
allow_url_fopen=Off和allow_url_include=Off,防止 POP 链中加载远程类或 phar:// 协议利用 - Web 服务器层(如 Nginx)对请求体中含
O:.*?:、C:.*?:正则模式的请求直接 403 拦截
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











