零基础入门反序列化及常用trick
字数 1735 2025-08-12 11:33:54
PHP反序列化漏洞全面解析与实战指南
一、序列化与反序列化基础
1. 基本概念
序列化是将数据结构或对象状态转换为可存储或传输的格式的过程,而反序列化则是将这些数据恢复为原始对象状态的过程。
$a = 'quan9i';
$b = serialize($a); // 序列化
$c = unserialize($b); // 反序列化
2. 序列化格式解析
对于类对象的序列化结果示例:
O:7:"xianzhi":2:{s:3:"age";s:2:"19";s:4:"name";s:6:"quan9i";}
格式说明:
O:7:"xianzhi":对象类型,类名长度7,类名"xianzhi":2::对象有2个属性{s:3:"age";s:2:"19";...}:属性列表,每个属性包含类型、长度、名称和值
3. 数据类型标识符
| 标识符 | 数据类型 |
|---|---|
| a | array |
| b | boolean |
| d | double |
| i | integer |
| o | common object |
| r | reference |
| s | string |
| C | custom object |
| O | class |
| N | null |
| R | pointer ref |
| U | unicode string |
二、PHP魔术方法详解
魔术方法是在特定事件发生时自动调用的方法,以双下划线开头:
1. 构造与析构方法
__construct():对象创建时调用__destruct():对象销毁时调用
class bai {
public function __construct() {
echo "初始化";
}
public function __destruct() {
echo "销毁";
}
}
2. 序列化相关方法
__sleep():在serialize()前调用,可指定要序列化的属性__wakeup():在unserialize()后调用
public function __sleep() {
return array('name', 'age');
}
public function __wakeup() {
$this->age = 1000;
}
3. 其他重要魔术方法
__toString():对象被当作字符串使用时调用__invoke():对象被当作函数调用时触发__get()/__set():访问/设置不可访问属性时调用__call():调用不存在的方法时触发__isset()/__unset():对不可访问属性使用isset()/unset()时触发
三、反序列化漏洞利用技术
1. 字符串逃逸
当存在字符串替换函数时,可通过精心构造payload实现逃逸:
// 原始代码
$umsg = str_replace('fuck', 'loveU', serialize($msg));
// 利用方式
$a = new message('fuckfuck...";s:5:"token";s:5:"admin";}','b','c');
利用步骤:
- 计算需要逃逸的字符串长度
- 构造足够数量的被替换字符串
- 在尾部添加闭合的序列化数据
2. 正则绕过
当存在正则过滤如preg_match('/^O:\d+/')时,可通过添加+号绕过:
O:+6:"Test":...
3. 引用利用
使用&符号创建变量引用,使两个变量保持同步:
$a = 'we are best';
$b = &$a; // $b和$a现在引用同一值
4. Session反序列化
PHP有三种session序列化处理器:
- php_serialize:完全序列化格式
a:1:{s:4:"name";s:5:"ocean";} - php(默认):简化格式
name|s:5:"ocean"; - php_binary:二进制格式
利用场景:当序列化和反序列化使用不同处理器时可能产生漏洞。
四、POP链构造技术
POP(Property-Oriented Programming)链是通过精心设计对象属性调用链来触发敏感操作的技术。
构造步骤:
- 寻找危险函数(如文件操作、命令执行等)
- 分析魔术方法和类方法的调用关系
- 构造调用链使程序流最终到达危险函数
示例分析:
// 目标:通过__destruct() -> __toString() -> __get() -> __invoke()链触发文件包含
class Modifier {
protected $var;
public function __invoke(){
$this->append($this->var); // 最终触发文件包含
}
}
class Show {
public function __toString(){
return $this->str->page; // 触发__get
}
}
class Test {
public function __get($key){
$function = $this->p;
return $function(); // 触发__invoke
}
}
五、实战案例解析
1. 简单反序列化利用
class ctfShowUser{
public $isVip = false;
public function vipOneKeyGetFlag(){
if($this->isVip){
echo $flag;
}
}
}
// 利用:直接修改isVip属性为true
2. 魔术方法利用
class backDoor{
private $code;
public function getInfo(){
eval($this->code); // 危险点
}
}
// 利用:通过反序列化设置$code为恶意代码
3. 文件操作利用
public function __destruct(){
file_put_contents("log-".$this->username, $this->password);
}
// 利用:设置username为"shell.php",password为PHP代码
六、防御措施
- 输入验证:严格检查反序列化数据来源
- 使用安全函数:如
hash_hmac()验证数据完整性 - 限制反序列化类:使用
allowed_classes选项 - 日志监控:记录反序列化操作
- 代码审计:避免在魔术方法中使用危险操作
七、工具与资源
- PHPGGC:PHP反序列化payload生成工具
- CodeBrute:自动化POP链构造工具
- 反序列化检测工具:如RIPS、SonarQube等
通过深入理解PHP反序列化机制和魔术方法,结合实际的漏洞利用技术,安全研究人员可以更好地发现和防御这类安全风险。