漏洞描述
近期 Apache
修复了Apache Kafka Connect
组件中的一个任意文件读取漏洞CVE-2025-27817
。该漏洞源于Kafka
对配置参数缺少检查,导致恶意攻击者可构造特殊URL
读取服务器上的任意文件或者实现SSRF
攻击,影响版本为:3.1.0~3.9.0
。此外,该漏洞还影响Apache Druid
等集成了Connect
组件的应用系统。
研究环境
为了快速分析,可以选择下载编译好的程序:
./zookeeper-server-start.sh ../config/zookeeper.properties./kafka-server-start.sh ../config/server.properties./connect-distributed.sh ../config/connect-distributed.properties
connect-distributed.sh
调用 kafka-run-class.sh
来启动进程,查看 kafka-run-class.sh
发现当环境变量 KAFKA_DEBUG
非空时将添加远程调试配置:
可以在 connect-distributed.sh
中加入环境变量定义以启动远程调试:
...export KAFKA_DEBUG=trueexec $(dirname $0)/kafka-run-class.sh $EXTRA_ARGS org.apache.kafka.connect.cli.ConnectDistributed "$@"
漏洞分析
CVE-2025-27817
与历史上的CVE-2023-25194
相似,触发接口都位于ConnectorsResource#createConnector
,分析时可以参考CVE-2023-25194
的构造过程。该接口传入的参数类型为CreateConnectorRequest
,其中包含一个名为config
的键值对。调试确认此时类中的herder
类型为DistributedHerder
:putConnectorConfig
函数,经过传递将调用validateConnectorConfig
验证传入的config
参数。该函数尝试从参数中读取key
为connector.class
的value
值,然后通过getConnector
来实例化Connector
对象。Kafka
中抽象类Connector
共有7
个子类:FileStreamSinkConnectorFileStreamSourceConnectorMirrorCheckpointConnectorMirrorHeartbeatConnectorMirrorSourceConnectorSinkConnectorSourceConnector
MirrorHeartbeatConnector
为例,当请求参数中connector.class
取值为MirrorHeartbeatConnector
时,会利用类中的start
函数创建一个Task
任务,并通过execute
启动任务子线程,而此时config
的值仍来自于用户请求 :DistributedHerder
类的startTask
函数执行任务,在后续处理中,会利用Worker#baseProducerConfigs
将config
中以producer.
开头的值赋值给新生成的producerProps
,并且新命名的key
去掉了producer.
头:public Map<String, Object> originalsWithPrefix(String prefix, boolean strip) { Map<String, Object> result = new RecordingMap(prefix, false); result.putAll(Utils.entriesWithPrefix(this.originals, prefix, strip)); return result; }
LoginManager#LoginManager
,并通过configure
函数进行配置,调用栈如下:configure
函数将根据 configs
的值来生成 accessTokenRetriever
和 accessTokenValidator
:
public void configure(Map<String, ?> configs, String saslMechanism, List<AppConfigurationEntry> jaasConfigEntries) { this.moduleOptions = JaasOptionsUtils.getOptions(saslMechanism, jaasConfigEntries); AccessTokenRetriever accessTokenRetriever = AccessTokenRetrieverFactory.create(configs, saslMechanism, this.moduleOptions); AccessTokenValidator accessTokenValidator = AccessTokenValidatorFactory.create(configs, saslMechanism); this.init(accessTokenRetriever, accessTokenValidator); }
AccessTokenRetrieverFactory#create
函数:尝试从配置中读取sasl.oauthbearer.token.endpoint.url
并赋值给URL
,当协议为file
时,会实例化一个FileTokenRetriever
对象:init
函数将触发文件读取操作,获取sasl.oauthbearer.token.endpoint.url
指向的文件内容:config
来实现任意文件读取。上述请求是创建connector
的过程,想要查看读取的文件内容可以通过另一个接口/status
实现:修复方式
AccessTokenRetrieverFactory
和VerificationKeyResolverFactory
中对URL
进行了限定:// visible for testing// make sure the url is in the "org.apache.kafka.sasl.oauthbearer.allowed.urls" system propertyvoid throwIfURLIsNotAllowed(String configName, String configValue) { throwIfResourceIsNotAllowed( "URL", configName, configValue, ALLOWED_SASL_OAUTHBEARER_URLS_CONFIG, ALLOWED_SASL_OAUTHBEARER_URLS_DEFAULT );}
原文始发于微信公众号(自在安全):CVE-2025-27817 Apache Kafka Connect 任意文件读取漏洞分析与复现
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论