
استغلال لإثبات المفهوم لثغرة CVE-2026-64638: XSS منعكسة في تسجيل دخول WordPress مقترنة بـ DOM clobbering لتحقيق الاستيلاء على حساب المسؤول وتنفيذ التعليمات البرمجية عن بُعد.
البرنامج: نواة ووردبريس ≤ 7.0.2 (جميع الإصدارات السابقة للإصدار 7.0.3)
CVSS: 8.9 (عالية)
CWE: CWE-79 — معالجة غير سليمة لإدخال المستخدم أثناء إنشاء صفحة الويب
المصادقة المطلوبة: لا شيء (قبل المصادقة)
تفاعل المستخدم: نشط (يحتاج المسؤول إلى النقر على رابط واحد)
الأثر: XSS → الاستيلاء على الحساب → تنفيذ التعليمات البرمجية عن بُعد
ووردبريس هو نظام إدارة المحتوى الأكثر شعبية في العالم، حيث يستحوذ على أكثر من 40% من جميع المواقع على الإنترنت. يحتوي كل موقع ووردبريس على صفحة تسجيل دخول على الرابط /wp-login.php — وهي نقطة نهاية عامة يمكن لأي شخص الوصول إليها دون مصادقة.
عندما يُدخل المستخدم اسم مستخدم غير صحيح، يعرض ووردبريس رسالة خطأ تحتوي على اسم المستخدم نفسه الذي كتبه المستخدم للتو: "اسم المستخدم X غير مسجل في هذا الموقع." تكمن المشكلة في أن قيمة اسم المستخدم تُوضع مباشرة في استجابة HTML دون المرور عبر أي دالة تهريب (escape) — كل ما يحتاجه المهاجم هو إدخال HTML/JavaScript بدلاً من اسم مستخدم حقيقي، وسيتم تنفيذ الكود في المتصفح.
هذه ثغرة XSS منعكسة (Reflected XSS) — الحمولة موجودة في الطلب ويعيدها الخادم مطابقة تمامًا في HTML. ما يجعلها خطيرة هو أن الثغرة تقع في صفحة تسجيل الدخول — وهو مكان يتردد عليه المسؤولون باستمرار، حيث يمكن سرقة ملفات تعريف ارتباط الجلسة الخاصة بالمسؤول.
اكتشف فريق البحث أيضًا أن هذه الثغرة يمكن ربطها بثغرة DOM Clobbering في مُحمّل الرموز التعبيرية (emoji-loader) في ووردبريس، مما يسمح بتحميل JavaScript من خادم خارجي. ومن هناك، يمكن للمهاجم إنشاء حساب مسؤول جديد ← تثبيت إضافة تحتوي على ويب شيل ← تنفيذ كود PHP على الخادم. يُشار إلى سلسلة الاستغلال هذه باسم XSS2Shell.
| السمة | القيمة |
|---|---|
| معرف CVE | CVE-2026-64638 |
| درجة CVSS | 8.9 (عالية) |
| البرنامج | نواة ووردبريس ≤ 7.0.2 |
| المصادقة | لا شيء مطلوب (قبل المصادقة) |
| تفاعل المستخدم | يتطلب نقرة واحدة (ينقر المسؤول على الرابط) |
| تعقيد الهجوم | عالٍ |
| تم التصحيح | ووردبريس 7.0.3 (08/06/2026) |
| المُبلِّغ | فريق pwn.ai عبر HackerOne |
| تقرير HackerOne | #3877102 |
يقوم ووردبريس بتحميل دعم الرموز التعبيرية في كل صفحة (بما في ذلك صفحة تسجيل الدخول) عبر الملف emoji-loader.js. يقرأ هذا السكربت الإعدادات من عنصر يحمل id="wp-emoji-settings":
// Before patch (vulnerable)
const settings = JSON.parse(
document.getElementById('wp-emoji-settings').textContent
);
تُرجع الدالة document.getElementById() أول عنصر في DOM يحمل معرفًا مطابقًا. إذا قام مهاجم بحقن <div id="wp-emoji-settings"> قبل وسم السكربت الأصلي، فستقرأ getElementById محتوى المهاجم بدلاً من الإعدادات الحقيقية. تُسمى هذه التقنية DOM Clobbering — استبدال سلوك JavaScript عن طريق حقن عناصر HTML.
يحتوي إعداد الرموز التعبيرية على رابط لتحميل ملف JavaScript (concatemoji). يتحكم المهاجم في هذا الرابط ← تحميل ملف JS من خادم خارجي ← تنفيذ كود تعسفي في سياق المتصفح.
بمجرد تحقيق تنفيذ JavaScript في سياق المسؤول، يحصل المهاجم على صلاحيات مسؤول ووردبريس كاملة:
/wp-admin/user-new.php بجلسة المسؤول/wp-admin/plugin-install.phpأي من الطرق الثلاث المذكورة أعلاه تتيح تنفيذ كود PHP على الخادم — أي RCE (تنفيذ التعليمات البرمجية عن بُعد).
من commit الإصلاح 0d6d42e في wordpress-develop، حددتُ 3 مواضع في الملف wp-includes/user.php حيث يُوضع اسم المستخدم/البريد الإلكتروني مباشرة في رسالة الخطأ:
# View diff between vulnerable and patched versions
git diff 7.0.2..7.0.3 -- src/wp-includes/user.php
الموضع 1 — السطر 189 (اسم المستخدم غير موجود):
قبل:
// BEFORE (vulnerable):
sprintf(
__( 'The username <strong>%s</strong> is not registered...' ),
$username // ← no escaping
)

بعد:
// fixed:
sprintf(
__( 'The username <strong>%s</strong> is not registered...' ),
esc_html( $username ) // ← escaped
)
الموضع 2 — السطر 216 (كلمة مرور خاطئة):
قبل:

// BEFORE:
'<strong>' . $username . '</strong>' // ← no escaping
بعد:
// AFTER:
'<strong>' . esc_html( $username ) . '</strong>'
الموضع 3 — السطر 299 (كلمة مرور خاطئة للبريد الإلكتروني):
قبل:

// BEFORE:
'<strong>' . $email . '</strong>' // ← no escaping
بعد:
// AFTER:
'<strong>' . esc_html( $email ) . '</strong>'
تدفق البيانات من طلب POST إلى رسالة الخطأ:
$_POST['log'] ← user input from login form
↓
wp_signon() [user.php:51]
$credentials['user_login'] = wp_unslash($_POST['log']) ← only removes backslashes
↓
wp_authenticate($username, $password) [pluggable.php:689]
$username = sanitize_user($username) ← strips HTML tags, but has a bypass
↓
wp_authenticate_username_password() [user.php:153]
get_user_by('login', $username) ← user not found
↓
sprintf('The username <strong>%s</strong>...', $username) ← XSS!
↓
WP_Error → login_header() → wp_admin_notice()
wp_kses_post(...) ← filters HTML but allows <div>, <a>, through
↓
HTML response → browser render → JavaScript execute
يمتلك ووردبريس طبقتين لتصفية الإدخال قبل وصول اسم المستخدم إلى HTML:
الطبقة 1: sanitize_user() — تستدعي strip_tags() لإزالة وسوم HTML. ومع ذلك، فإن strip_tags() في PHP لها حدود معروفة: التنسيق غير القياسي للوسوم يمكن أن يتجاوز الفلتر.
الطبقة 2: wp_kses_post() — تسمح بمرور مجموعة فرعية آمنة من HTML، بما في ذلك <div> و<a> و`` بخصائص معينة (ولكنها تزيل معالجات الأحداث مثل onerror وonload). الأهم: wp_kses_post تسمح بمرور <div id="wp-emoji-settings"> — وهو بالضبط العنصر المطلوب لـ DOM Clobbering.
وجد فريق pwn.ai طريقة لتجاوز الطبقتين لحقن حمولة مفيدة. لم يتم الكشف عن التفاصيل التقنية الدقيقة علنًا.
للتأكد بصريًا من أن اسم المستخدم ينتقل مباشرة إلى HTML دون تهريب، استخدمتُ Xdebug + VS Code لوضع نقاط توقف (breakpoints) عند نقاط رئيسية في سلسلة التنفيذ.
الخطوة 1 — إدخال حمولة XSS في نموذج تسجيل الدخول:
الوصول إلى http://localhost:8282/wp-login.php، أدخل اسم المستخدم كالتالي `` ثم انقر على "تسجيل الدخول". تظهر نافذة تنبيه — XSS تعمل.


الخطوة 2 — نقطة توقف عند user.php:184 — مكان حدوث XSS:
ضع نقطة توقف عند return new WP_Error(...) داخل الدالة wp_authenticate_username_password(). عندما يتوقف مصحح الأخطاء، لاحظ:
$username = "" — حمولة HTML سليمة وغير مُهرَّبة$_POST: log = "" — يؤكد أن الحمولة مصدرها إدخال النموذجwp_authenticate_username_password() → WP_Hook->apply_filters → apply_filters → wp_authenticate → wp_signon → {main} wp-login.php