PHP 7.3反序列化审计核心三步:确认unserialize()输入可控、类可利用、魔术方法危险;重点审__wakeup()和__destruct(),排查POP链,注意$options参数与环境配置影响。

直接看 unserialize() 调用点,确认输入是否可控、类是否可利用、魔术方法是否危险——这是PHP 7.3下审计反序列化漏洞最核心的三步。
定位所有反序列化入口
全局搜索以下关键词,重点关注用户可控输入参与的调用:
-
unserialize(—— 最直接的入口,必须逐个检查参数来源 -
$_GET、$_POST、$_COOKIE、$_REQUEST、$_SESSION中是否被直接或间接传入unserialize() - 常见高危位置:Session反序列化(如
session_decode()配合自定义 handler)、Cookie解析、API参数解析、缓存反取(如 Redis/Memcached 中取出后直接反序列化) - 注意别名或封装:比如函数名是
safe_unserialize(),但内部仍调用原生unserialize(),需跟进到底
检查类定义与魔术方法行为
找到被反序列化的类(从序列化字符串中提取类名,如 O:8:"DBConfig":... 中的 DBConfig),然后审计其源码:
- 重点看
__wakeup():PHP 7.3 仍默认触发,且在反序列化完成瞬间执行;若含file_get_contents、include、system或数据库操作,极易被利用 - 重点看
__destruct():对象生命周期结束时必触发,常用于资源清理,但若存在未过滤的属性拼接(如unlink($this->path)),就构成删除任意文件风险 - 顺带排查
__toString()、__invoke()、__call():这些可能在后续链式调用中被间接触发(例如对象被 echo、被当作函数调用、或调用不存在方法时) - 注意属性可见性:
private属性在序列化中会带"\0Classname\0"前缀,protected带"\0*\0",构造恶意 payload 时必须严格匹配,否则反序列化失败
验证是否存在POP链或危险组合
单个类未必有明显漏洞,但多个类组合可能形成利用链(POP Chain):
- 找“中间类”:比如一个类的
__destruct()调用了另一个类的方法,而该方法又使用了可控属性(如$this->handler->run($this->data)) - 找“触发类”:如
SimpleXMLElement的__toString()可发起 HTTP 请求;Exception在某些上下文中可泄露路径;Phar扩展启用时,反序列化 Phar 文件元数据也会触发(虽非unserialize()直接调用,但属同类风险) - PHP 7.3 默认禁用
phar.stream.wrapper(需手动开启),但若项目显式启用,unserialize(file_get_contents('phar://a.phar'))就可能绕过常规检测 - 用工具辅助:PHPGGC 可快速生成已知组件(如 Laravel、Monolog、SwiftMailer)的 POP 链;也可用
php -d "display_errors=1" -r 'unserialize("...");'本地验证 payload 是否成功触发
确认环境与配置影响
PHP 7.3 的某些特性会影响漏洞表现,审计时不能忽略:
-
unserialize()的$options参数(PHP 7.0+ 支持):若代码用了unserialize($data, ['allowed_classes' => false]),则完全禁止对象反序列化,相对安全;若为['allowed_classes' => ['User', 'Log'],则只允许白名单类,需检查白名单内类是否真安全 -
error_reporting和display_errors:若开启,错误信息可能泄露类名、路径或反序列化失败原因,辅助攻击者调试 payload - 扩展限制:PHP 7.3 默认不加载
igbinary或msgpack,但若项目手动启用并使用igbinary_unserialize()等替代函数,也需一并纳入审计范围 - 注意
__wakeup()的兼容性:PHP 7.3 仍支持,且不会因类中无该方法而报错;但若类定义了__wakeup()却没做parent::__wakeup()(继承场景),可能引发逻辑异常,间接导致绕过校验
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











