PHP反序列化
PHP反序列化漏洞
一、基础概念
1. PHP序列化
- 定义:将复杂数据结构转换为字符串以便传输或存储。
- 函数:
serialize() - 示例:
$data = ["name" => "test", "age" => 20];
echo serialize($data);
// 输出:a:2:{s:4:"name";s:4:"test";s:3:"age";i:20;}
2. PHP反序列化
- 定义:将序列化字符串恢复为原始数据结构。
- 函数:
unserialize() - 风险:若参数可控且未校验,可导致对象注入漏洞。
3. 反序列化漏洞
- 别名:PHP对象注入(PHP Object Injection)
- 成因:
- 使用
unserialize()且参数可控 - 类中定义了危险魔术方法(如
__wakeup())
- 使用
二、常见魔术方法
| 魔术方法 | 触发条件 |
|---|---|
__construct() |
对象创建时自动调用 |
__destruct() |
对象销毁时自动调用 |
__wakeup() |
调用unserialize()时触发 |
__sleep() |
调用serialize()时触发 |
__toString() |
对象被当作字符串使用时触发 |
__invoke() |
对象被当作函数调用时触发 |
__call() |
调用不存在或不可访问的方法时触发 |
三、序列化格式解析
示例序列化字符串:
O:10:"ThreeBody":1:{s:4:"name";s:4:"test";}
| 部分 | 说明 |
|---|---|
O |
表示对象(Object) |
10 |
类名长度 |
"ThreeBody" |
类名 |
1 |
对象属性数量 |
s:4:"name" |
字符串属性名(长度4) |
s:4:"test" |
字符串属性值(长度4) |
四、漏洞实例分析
漏洞代码
class A {
public $test = "demo";
public function __wakeup() {
eval($this->test); // 高危操作:执行任意代码
}
}
// 序列化示例
$b = new A();
echo serialize($b);
// 输出:O:1:"A":1:{s:4:"test";s:4:"demo";}
// 反序列化触发点
$a = $_GET["test"];
$a_unser = unserialize($a);
攻击Payload
http://target.com/vuln.php?test=O:1:"A":1:{s:4:"test";s:10:"phpinfo();";}
漏洞原理
- 攻击者控制
$test属性值为phpinfo(); - 反序列化时触发
__wakeup()执行eval("phpinfo();")
五、防御措施
1. 输入控制
// 禁止直接反序列化用户输入
$allowed_classes = [];
$data = unserialize($_GET['data'], ['allowed_classes' => $allowed_classes]);
2. 使用安全替代方案
// 优先使用JSON
$data = json_decode($_GET['data'], true);
3. 安全配置
; php.ini配置
disable_functions = eval,exec,passthru
六、拓展工具
- PHPGGC:反序列化Payload生成工具
- RIPS:静态代码分析工具
最后更新:2024年9月12日

浙公网安备 33010602011771号