基础知识丨PHP序列化
概述
PHP序列化是把变量转换成可存储或传输的字符串的过程,反序列化则是把这个字符串恢复成原来的PHP常量,与JAVA序列化类似。它在保存会话、缓存数据或在不同系统间传递复杂结构时很有用。主要依靠serialize函数与unserialize函数。
用法示例
$data = ['name' => 'Alice', 'age' => 28, 'score' => 9.5];
$str = serialize($data); // 序列化
$back = unserialize($str); // 反序列化
echo $str;
// a:3:{s:4:"name";s:5:"Alice";s:3:"age";i:28;s:5:"score";d:9.5;}
序列化格式
PHP序列化中,不同类型有固定对应的标记
| 类型 | 格式示例 |
|---|---|
| NULL | N; |
| 布尔 | b:1;或b:0; |
| 整数 | i:28; |
| 浮点 | d:0.1; |
| 字符串 | s:3:"Ark"(长度为3的字符串"Ark") |
| 数组 | a:2:{i:0;s:3:"Ark";b:1;......} |
对象序列化格式实例如下:
class User {
public $name = 'Bob';
protected $email = 'bob@example.com';
private $password = 'secret';
}
echo serialize(new User);
// O:4:"User":3:{s:4:"name";s:3:"Bob";s:8:"\0*\0email";s:16:"bob@example.com";s:13:"\0User\0password";s:6:"secret";}
对于public属性,直接写属性名;对于protected属性,属性名前加"\0*\0";对于private属性,属性名前加"\0类名\0"
PHP反序列化漏洞
魔术方法
魔术方法(Magic Methods)是 PHP 中一类特殊的方法,它们由 PHP 引擎在特定的“魔法时刻”自动调用,而不需要开发者手动去触发。可以理解成事件钩子。
POP链
全称是 Property-Oriented Programming,就是从反序列化入口开始,通过一系列魔术方法的接力调用,最终触达危险函数的路径。
简单的POP链示例如:
class Start {
public $obj;
function __destruct() {
// 销毁时调用某个对象的 close() 方法
$this->obj->close();
}
}
class Evil {
public $command;
function close() {
// 这里执行系统命令
system($this->command);
}
}
// 攻击者构造的 payload 序列化字符串:
// O:5:"Start":1:{s:3:"obj";O:4:"Evil":1:{s:7:"command";s:2:"id";}}
$payload = $_GET['data'];
unserialize($payload); // 脚本结束时触发 __destruct(),执行 system("id")
漏洞成因
当unserialize函数的参数可以被攻击者控制的时候,攻击者就可以构造一个恶意的序列化字符串,在反序列化时便会自动触发对象里的魔术方法,最终形成一条攻击链(叫POP链),实现任意代码执行、文件操作等破坏
即使代码里面从来没有正常创建过危险的类,但只要类定义存在,攻击者就可以在序列化字符串中指明这个类,反序列化时PHP就会重建它的对象,并自动调用魔术方法。
必要条件
- unserialize() 的参数是用户可控制的
- 代码中存在至少一个类,其中魔术方法内存在可能被利用的危险操作
- 危险操作调用了类似system()等敏感函数,且参数可以间接被控制
其他利用技巧
利用protected/private属性的空字符
序列化字符串中,protected 属性会带有"\0*\0",private 属性带有"\0类名\0"。这些空字符在 URL 或手工构造 payload 时可能需要编码处理。攻击者会利用这一特性来精确控制属性的可见性,绕过某些浅层的检查。
绕过__wakeup
在某些旧版本(PHP 5 < 5.6.25, PHP 7 < 7.0.10)中,当序列化字符串里对象属性的个数大于实际属性个数时,__wakeup()不会被调用
O:4:"User":2:{s:3:"age";i:20;} // 实际属性数是1,但写成了2,可绕过 __wakeup
PHAR反序列化
即使代码里没有unserialize(),使用phar://伪协议操作文件时,也会自动触发反序列化。当文件系统操作被执行时,PHP 会解析 PHAR 文件的元数据并反序列化,元数据可以是攻击者精心构造的 payload。
Session反序列化
如果应用将序列化数据存储在 Session 中,并且修改了session.serialize_handler,攻击者可能通过巧妙污染 Session 数据,使unserialize()调用时处理混合了不同处理器的恶意串,从而注入对象。
更多推荐

所有评论(0)