PHP序列化与反序列化通俗详解
基本概念比喻
想象你有一盒乐高玩具:
- 序列化:把搭建好的乐高模型拆解,所有零件按规则放入包装盒(变成字符串)
- 反序列化:按图纸从盒子里取出零件重新组装成模型(字符串变回对象)
一、序列化(Serialization)
将对象或数据结构转换成可存储/传输的字符串格式。
示例代码
class User {
public $name = 'Hacker';
private $id = 1001;
protected $role = 'admin';
public function showRole() {
return $this->role;
}
}
$user = new User();
$serialized = serialize($user);
echo $serialized;
输出结果
O:4:"User":3:{
s:4:"name";s:6:"Hacker";
s:7:"\0User\0id";i:1001;
s:9:"\0*\0role";s:5:"admin";
}
格式解析:
O:对象(Object)4:类名长度("User")"User":类名3:属性数量s:4:"name":字符串属性,长度4,名称"name"s:6:"Hacker":字符串值,长度6s:7:"\0User\0id":私有属性格式\0类名\0属性名s:9:"\0*\0role":保护属性格式\0*\0属性名
二、反序列化(Unserialization)
将序列化字符串还原为PHP对象或数据结构
$data = 'O:4:"User":3:{s:4:"name";s:6:"Hacker";s:7:"\0User\0id";i:1001;s:9:"\0*\0role";s:5:"admin";}';
$restored = unserialize($data);
echo $restored->showRole(); // 输出"admin"
三、安全风险:反序列化漏洞原理
危险根源:魔术方法
PHP在反序列化时会自动调用特殊方法:
| 魔术方法 | 触发时机 | 常见风险操作 |
|---|---|---|
__wakeup() | 反序列化后立即执行 | 数据库连接/文件操作 |
__destruct() | 对象销毁时执行 | 删除文件/写入日志 |
__toString() | 对象被当作字符串使用 | XSS/代码拼接 |
漏洞示例代码
class Dangerous {
public $cmd;
public function __destruct() {
system($this->cmd); // 对象销毁时执行系统命令
}
}
// 攻击者构造的恶意序列化数据
$evil = 'O:9:"Dangerous":1:{s:4:"cmd";s:8:"whoami";}';
// 受害者反序列化恶意数据
$obj = unserialize($evil); // 此时对象创建
// 脚本结束时$obj自动销毁,触发__destruct()执行whoami命令
四、CTF中的典型利用方式
1. 直接命令执行
class Payload {
function __wakeup() {
echo shell_exec($this->cmd);
}
}
unserialize($_COOKIE['payload']);
2. 文件操作(写webshell)
class WebShell {
function __destruct() {
file_put_contents(
$this->filename,
'<?php system($_GET["cmd"]);?>'
);
}
}
// 序列化payload:设置filename=shell.php
3. POP链攻击
组合多个类的魔术方法实现复杂攻击:
class Database {
public $connection;
function __destruct() {
$this->connection->exec($this->query);
}
}
class Connection {
public $sql;
function exec($sql) {
system($this->sql);
}
}
// 构造链式触发:
// Database销毁 -> 调用Connection的exec -> 执行系统命令
五、防御措施
1、永远不要反序列化用户输入
// 绝对禁用
unserialize($_POST['data']);
2、使用JSON等安全格式替代
// 安全做法
json_decode($_POST['data'], true);
3、限制可用类(PHP 7+)
$data = unserialize($serialized, [
'allowed_classes' => ['SafeClass']
]);
4、严格校验数据
if(!preg_match('/^[a-z0-9]+$/', $data)) {
die("Invalid data");
}
现实类比总结
- 序列化:将武器拆解后放入快递箱
- 反序列化:收件人重新组装武器
- 漏洞:攻击者篡改零件,组装成定时炸弹
- 防御:只接收信任来源的零件,严格验货
在CTF竞赛中,理解序列化机制是解决Web类题目的关键技能之一!

1万+

被折叠的 条评论
为什么被折叠?



