Yucaerin/CVE-2026-5118
GitHub: Yucaerin/CVE-2026-5118
Stars: 0 | Forks: 1
# CVE-2026-5118 — Divi Form Builder <= 5.1.2 — Unauthenticated Privilege Escalation via Role Injection
🔥 **Vulnerability Summary**
The vulnerability stems from the `create_user()` function in `FormSubmissionHandler.php`, which accepts the `role` parameter directly from user-submitted POST data without proper authorization or allowlist validation. The plugin only checks whether the submitted role **exists** in the system (e.g., `administrator` is a valid WordPress role) — it never checks whether the role is **safe** for public registration.
**Breakthrough Discovery:** The `fb_nonce` used by Divi Form Builder is a **global shared nonce** (`wp_create_nonce('security')`) — identical across all forms on the site. Furthermore, `form_type=register` can be **overridden via POST** to the shared AJAX handler. This means any DFB form (contact, quote, feedback, etc.) can be weaponized to trigger user registration with arbitrary role assignment.
🔍 **Affected Plugin**
- **Plugin Name:** Divi Form Builder
- **Affected Version:** <= 5.1.2
- **Vulnerability Type:** Unauthenticated Privilege Escalation via Role Injection
- **CVE ID:** CVE-2026-5118
- **CVSS Score:** 9.8 (Critical)
- **CWE:** CWE-266 — Incorrect Privilege Assignment
- **Impact:** Full Site Takeover — Admin Account Creation
🧨 **What Attackers Can Do**
| Capability | Impact |
|---|---|
| 🔑 Create admin account without login | **Full Site Takeover** |
| 📦 Access WooCommerce customer data | **Data Breach** |
| 💉 Edit plugin/theme PHP files | **Remote Code Execution** |
| 🕳️ Install hidden backdoors | **Persistent Access** |
| 👥 View all user data | **Privacy Violation** |
🧪 **Exploit Features**
- 🔓 **No authentication required**
- 📝 **Works through ANY DFB form** — contact, quote, newsletter, feedback, etc.
- 🎯 **Targets the AJAX endpoint** `/wp-admin/admin-ajax.php?action=de_fb_ajax_submit_ajax_handler`
- 🧠 **Role injection** — submits `role=administrator` alongside normal form fields
- 🌐 **Mass scanning support** — threaded multi-target scanner with auto-discovery
- 📄 **Results saved to** `result.txt`
🧠 **Vulnerable Code**
// includes/shared/handlers/FormSubmissionHandler.php ~ line 2250
$role = isset($form_data['role']) ? sanitize_text_field($form_data['role']) : 'subscriber';
// ~ line 2278 — ONLY checks if role EXISTS, not if it is SAFE
$roles_obj = function_exists('wp_roles') ? wp_roles() : null;
if ($roles_obj && is_object($roles_obj) && is_array($roles_obj->roles) && !isset($roles_obj->roles[$role])) {
$role = 'subscriber'; // ← "administrator" EXISTS, so this check PASSES
}
// ~ line 2301 — Directly applies the injected role
$user = new WP_User($user_id);
$user->set_role($role); // ← PRIVILEGE ESCALATION!
🚀 **Usage**
### Single Target
python3 exploit.py -t http://target.com
python3 exploit.py -t https://target.com -u hacker -p Pass123! -e hack@proton.me
### Mass Scan (List without http/https)
Create `targets.txt`:
target1.com
target2.com:8080
192.168.1.50
subdomain.target.com
python3 exploit.py -l targets.txt -T 20
### Options
| Flag | Description |
|---|---|
| `-t, --target` | Single target URL |
| `-l, --list` | File with target list (one per line, http/https optional) |
| `-T, --threads` | Threads for mass scan (default: 10) |
| `-o, --output` | Output file for results (default: `result.txt`) |
| `-u, --username` | Custom username for new account |
| `-p, --password` | Custom password for new account |
| `-e, --email` | Custom email for new account |
| `-v, --verbose` | Verbose debug output |
| `--no-confirm` | Skip permission confirmation prompt |
🛠 **Fix Recommendations**
// SECURE: Allowlist only safe roles for public registration
$allowed_registration_roles = array('subscriber', 'contributor');
if (!in_array($role, $allowed_registration_roles, true)) {
$role = 'subscriber'; // ← Reject ALL dangerous roles
}
- Remove the `role` hidden input from frontend forms entirely
- Add `current_user_can('create_users')` capability checks for privileged roles
- Implement strict nonce verification scoped per-form instead of global
- Add rate limiting on the registration AJAX endpoint
🧠 **Researcher**
- Credit: [0xd4rk5id3](https://www.wordfence.com/threat-intel/vulnerabilities/researchers/0xd4rk5id3)
📚 **References**
- [Wordfence Advisory](https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/divi-form-builder/divi-form-builder-512-unauthenticated-privilege-escalation-via-role)
- [Original CVE Repository](https://github.com/zycoder0day/CVE-2026-5118)
🔒 **Disclaimer:**
This information is provided for **educational** and **authorized penetration testing** purposes only. Unauthorized exploitation of computer systems is illegal and unethical. Always obtain explicit written permission before testing any target you do not own.