Java反序列化深度讲解(二)
字数 1956 2025-08-10 16:34:25
Java反序列化漏洞深度解析
一、序列化与反序列化基础概念
1.1 序列化的本质
序列化和反序列化是一种数据通信思想:
- 序列化:将复杂数据结构"打包"成特定格式的数据流
- 反序列化:将序列化数据"解包"还原为原始数据结构
1.2 Java中的序列化实现方式
1.2.1 Java原生序列化
import java.io.*;
// 实现Serializable标记接口
public class MyClass implements Serializable {
static int value = 100;
static String name = "TestClass";
MyClass() {
System.out.println(name + value);
}
}
// 序列化
MyClass myObject = new MyClass();
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("data.bin"))) {
oos.writeObject(myObject);
}
// 反序列化
MyClass deserializedObject;
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.bin"))) {
deserializedObject = (MyClass) ois.readObject();
}
1.2.2 JSON序列化(以Jackson为例)
import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper objectMapper = new ObjectMapper();
// 序列化为JSON字符串
String json = objectMapper.writeValueAsString(myObject);
// 从JSON反序列化
MyClass deserializedObject = objectMapper.readValue(json, MyClass.class);
1.2.3 XML序列化(以JAXB为例)
import javax.xml.bind.*;
// 序列化为XML
JAXBContext context = JAXBContext.newInstance(MyClass.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
StringWriter writer = new StringWriter();
marshaller.marshal(myObject, writer);
String xml = writer.toString();
// 从XML反序列化
Unmarshaller unmarshaller = context.createUnmarshaller();
MyClass deserializedObject = (MyClass) unmarshaller.unmarshal(new StringReader(xml));
1.2.4 其他序列化库
- Apache Avro
- Google Protocol Buffers
二、反序列化漏洞原理
2.1 Java与PHP反序列化的关键区别
| 特性 | Java反序列化 | PHP反序列化 |
|---|---|---|
| 控制范围 | 可传入任意类构造恶意数据 | 只能控制已有类的属性值 |
| 利用条件 | 可利用Java标准库中的危险方法 | 依赖系统中已存在的危险函数 |
| 灵活性 | 高,可自定义序列化逻辑 | 低,受限于现有类结构 |
2.2 Java反序列化漏洞的核心原因
- 自定义序列化逻辑:通过
writeObject()和readObject()方法可以完全控制序列化/反序列化过程 - 动态类加载:反序列化时可以加载并实例化任意类
- 方法调用链:通过精心构造的调用链(Gadget Chains)可执行任意代码
2.3 典型攻击场景
攻击者通过构造恶意序列化数据,利用以下机制实现攻击:
- 利用反射机制调用危险方法
- 通过动态代理执行恶意操作
- 触发类加载时执行的静态代码块
- 利用自动类型转换机制
三、防御措施
3.1 基本防御策略
- 避免反序列化不可信数据
- 使用白名单机制:限制可反序列化的类
- 使用安全替代方案:如JSON、Protocol Buffers等
3.2 具体防护实现
3.2.1 使用ObjectInputFilter
ObjectInputStream ois = new ObjectInputStream(inputStream);
ois.setObjectInputFilter(filter);
3.2.2 自定义白名单过滤器
public class SafeObjectInputStream extends ObjectInputStream {
private static final Set<String> ALLOWED_CLASSES =
Set.of("java.lang.String", "java.util.HashMap", "com.example.SafeClass");
@Override
protected Class<?> resolveClass(ObjectStreamClass desc)
throws IOException, ClassNotFoundException {
if (!ALLOWED_CLASSES.contains(desc.getName())) {
throw new InvalidClassException("Unauthorized deserialization attempt", desc.getName());
}
return super.resolveClass(desc);
}
}
四、历史漏洞与攻击链分析
4.1 常见攻击链(CC链)
CC链(Commons Collections链)是Java反序列化中最著名的攻击链之一,利用Apache Commons Collections库中的以下关键类:
- Transformer接口:定义对象转换逻辑
- InvokerTransformer:通过反射调用任意方法
- ChainedTransformer:将多个Transformer串联执行
- TransformedMap/LazyMap:在特定操作时自动执行Transformer
4.2 攻击链构造示例
Transformer[] transformers = new Transformer[] {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",
new Class[]{String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}),
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}),
new InvokerTransformer("exec",
new Class[]{String.class},
new Object[]{"calc.exe"})
};
Transformer chain = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
Map outerMap = TransformedMap.decorate(innerMap, null, chain);
五、深入分析技术细节
5.1 Java序列化协议解析
Java序列化流格式:
- 魔数:
AC ED(标识Java序列化流) - 版本号:
00 05(当前版本) - 内容:TC_OBJECT(0x73)标识对象开始
5.2 关键危险方法
- Runtime.exec():直接执行系统命令
- Method.invoke():通过反射调用任意方法
- Class.newInstance():动态实例化类
- URLClassLoader.loadClass():动态加载远程类
5.3 反序列化过程分析
- readObject():ObjectInputStream的核心反序列化方法
- readOrdinaryObject():处理普通对象反序列化
- readClassDesc():读取类描述信息
- resolveClass():解析类定义(关键扩展点)
六、实战检测与利用
6.1 漏洞检测方法
- 黑盒测试:发送测试序列化数据观察响应
- 白盒审计:检查反序列化点是否过滤输入
- 工具辅助:使用ysoserial等工具生成测试payload
6.2 利用工具链
- ysoserial:生成各种Gadget Chains
- marshalsec:快速搭建恶意RMI/LDAP服务器
- Burp Suite插件:JavaSerialKiller等
七、高级话题
7.1 绕过防御的技术
- 使用冷门Gadget Chains:避开常见检测规则
- 利用JNDI注入:结合LDAP/RMI实现远程类加载
- 动态字节码生成:在内存中构造恶意类
7.2 最新研究方向
- 自动化Gadget Chain发现:通过静态分析寻找新利用链
- 机器学习检测:识别异常序列化模式
- 内存防护技术:防止反序列化时的代码执行
八、总结
Java反序列化漏洞的核心在于:
- 反序列化过程等同于对象构造+初始化
- Java允许完全控制这一过程
- 丰富的标准库提供了大量可利用的方法调用链
防御的关键在于:
- 严格控制反序列化源
- 限制可反序列化的类
- 监控反序列化过程中的异常行为