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反序列化漏洞的核心原因

  1. 自定义序列化逻辑:通过writeObject()readObject()方法可以完全控制序列化/反序列化过程
  2. 动态类加载:反序列化时可以加载并实例化任意类
  3. 方法调用链:通过精心构造的调用链(Gadget Chains)可执行任意代码

2.3 典型攻击场景

攻击者通过构造恶意序列化数据,利用以下机制实现攻击:

  1. 利用反射机制调用危险方法
  2. 通过动态代理执行恶意操作
  3. 触发类加载时执行的静态代码块
  4. 利用自动类型转换机制

三、防御措施

3.1 基本防御策略

  1. 避免反序列化不可信数据
  2. 使用白名单机制:限制可反序列化的类
  3. 使用安全替代方案:如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库中的以下关键类:

  1. Transformer接口:定义对象转换逻辑
  2. InvokerTransformer:通过反射调用任意方法
  3. ChainedTransformer:将多个Transformer串联执行
  4. 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序列化流格式:

  1. 魔数:AC ED(标识Java序列化流)
  2. 版本号:00 05(当前版本)
  3. 内容:TC_OBJECT(0x73)标识对象开始

5.2 关键危险方法

  1. Runtime.exec():直接执行系统命令
  2. Method.invoke():通过反射调用任意方法
  3. Class.newInstance():动态实例化类
  4. URLClassLoader.loadClass():动态加载远程类

5.3 反序列化过程分析

  1. readObject():ObjectInputStream的核心反序列化方法
  2. readOrdinaryObject():处理普通对象反序列化
  3. readClassDesc():读取类描述信息
  4. resolveClass():解析类定义(关键扩展点)

六、实战检测与利用

6.1 漏洞检测方法

  1. 黑盒测试:发送测试序列化数据观察响应
  2. 白盒审计:检查反序列化点是否过滤输入
  3. 工具辅助:使用ysoserial等工具生成测试payload

6.2 利用工具链

  1. ysoserial:生成各种Gadget Chains
  2. marshalsec:快速搭建恶意RMI/LDAP服务器
  3. Burp Suite插件:JavaSerialKiller等

七、高级话题

7.1 绕过防御的技术

  1. 使用冷门Gadget Chains:避开常见检测规则
  2. 利用JNDI注入:结合LDAP/RMI实现远程类加载
  3. 动态字节码生成:在内存中构造恶意类

7.2 最新研究方向

  1. 自动化Gadget Chain发现:通过静态分析寻找新利用链
  2. 机器学习检测:识别异常序列化模式
  3. 内存防护技术:防止反序列化时的代码执行

八、总结

Java反序列化漏洞的核心在于:

  1. 反序列化过程等同于对象构造+初始化
  2. Java允许完全控制这一过程
  3. 丰富的标准库提供了大量可利用的方法调用链

防御的关键在于:

  1. 严格控制反序列化源
  2. 限制可反序列化的类
  3. 监控反序列化过程中的异常行为
Java反序列化漏洞深度解析 一、序列化与反序列化基础概念 1.1 序列化的本质 序列化和反序列化是一种数据通信思想: 序列化 :将复杂数据结构"打包"成特定格式的数据流 反序列化 :将序列化数据"解包"还原为原始数据结构 1.2 Java中的序列化实现方式 1.2.1 Java原生序列化 1.2.2 JSON序列化(以Jackson为例) 1.2.3 XML序列化(以JAXB为例) 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 3.2.2 自定义白名单过滤器 四、历史漏洞与攻击链分析 4.1 常见攻击链(CC链) CC链(Commons Collections链)是Java反序列化中最著名的攻击链之一,利用Apache Commons Collections库中的以下关键类: Transformer接口 :定义对象转换逻辑 InvokerTransformer :通过反射调用任意方法 ChainedTransformer :将多个Transformer串联执行 TransformedMap/LazyMap :在特定操作时自动执行Transformer 4.2 攻击链构造示例 五、深入分析技术细节 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允许完全控制这一过程 丰富的标准库提供了大量可利用的方法调用链 防御的关键在于: 严格控制反序列化源 限制可反序列化的类 监控反序列化过程中的异常行为