PHP序列化漏洞 重点知识总结
一、基础概念
-
序列化/反序列化
-
serialize():将变量、对象转为可存储/传输的字符串(打包)。 -
unserialize():将序列化字符串还原为原数据(拆包),必须先序列化再反序列化。 -
作用:数据持久化存储、跨环境数据传递。
-
-
格式标识
-
s:长度:"字符串":字符串类型;i:数字:整型;O:类名长度:"类名":属性数:{属性内容}:对象类型。
-
二、无类序列化(基础考点)
核心逻辑:反序列化结果与目标值全等(===) 即可触发逻辑、获取Flag。
-
常规场景 直接对目标字符串序列化,通过GET/POST/Cookie传入参数即可。 示例:目标值
derry→ 序列化结果s:5:"derry";。 -
代码审计坑点 若变量定义在判断逻辑之后,目标变量实际为空字符串,需序列化空值:
s:0:"";。
三、类序列化 & PHP魔术方法(核心漏洞点)
1. 类序列化规则
对象序列化会保留类名、属性、属性值;反序列化会重建对象,自动触发对应魔术方法。
-
public属性:序列化直接显示属性名; -
protected/private属性:序列化会携带\00空字符,URL传输需注意编码,也是CTF常见坑点。
2. 高频魔术方法(漏洞触发核心)
反序列化过程中满足条件会自动调用,是漏洞利用的关键:
| 方法 | 触发时机 | 用途/考点 |
|---|---|---|
__construct |
对象创建(new)时 | 构造方法,反序列化不主动触发,多为干扰代码 |
__destruct |
对象销毁、脚本执行结束 | 最常用漏洞入口,反序列化结束必触发 |
__sleep |
序列化对象时 | 自定义序列化保留的属性 |
__wakeup |
反序列化重建对象时 | 常规反序列化优先执行,可被漏洞绕过 |
__toString |
对象被当作字符串输出时 | 常用于原生类XSS利用 |
__get/__set |
访问/赋值不存在/私有属性 | 属性调用触发 |
__call/__callStatic |
调用不存在(静态)方法 | 方法调用触发 |
__invoke |
对象被当作函数调用 | 小众考点 |
__isset/__unset |
检测/销毁不可访问属性 | 辅助考点 |
四、经典CTF真题&漏洞利用
1. 网鼎杯 AreUSerialz(类序列化+魔术方法)
-
核心逻辑:依靠
__destruct触发process()方法,op=2时执行文件读取,调用NewFlag::getFlag()获取Flag。 -
难点:目标类属性为
protected,直接序列化含\00空字符,URL传参解析异常。 -
解法:将类属性改为
public再序列化,规避空字符问题,构造合法序列化字符串传入。
2. 极客大挑战2019 PHP(CVE-2016-7124)
-
漏洞原理:PHP版本低于
5.6.25 / 7.0.10时,若序列化字符串中声明的属性数量 > 类真实属性数,会跳过__wakeup执行。 -
利用步骤:
-
扫描获取网站备份
www.zip,审计源码发现反序列化入口与__wakeup防护; -
篡改序列化字符串:增大属性计数值,绕过
__wakeup; -
类属性为
private,序列化结果自带%00类名%00前缀,直接URL传参。
-
3. 原生类反序列化XSS
-
原理:利用PHP内置原生类(无需自定义类),反序列化后输出对象触发
__toString。 -
常用类:
Exception、Error; -
利用方式:构造异常对象,传入XSS载荷
<script>alert(1)</script>,序列化后URL编码传参,实现弹窗。
五、关键防护与考点总结
-
核心攻击链 可控参数 → 传入恶意序列化字符串 →
unserialize()重建对象 → 自动触发魔术方法 → 执行恶意代码/读取文件/XSS。 -
高频坑点
-
代码顺序:变量定义位置决定目标值;
-
访问修饰符:
public/protected/private影响序列化格式与URL传输; -
版本漏洞:CVE-2016-7124 绕过
__wakeup; -
特殊字符:
\00空字符在URL中需编码,易解析失败。
-
-
基础防御
-
严格过滤
unserialize()的入参,不接收用户可控的序列化数据; -
升级PHP版本,修复已知反序列化漏洞;
-
对敏感类、魔术方法做权限与逻辑限制。
-
更多推荐


所有评论(0)