Skip to content
KitploitKITPLOIT
أدواتعمليات الاستغلالالمدونة
Log in
إرسال
أدواتعمليات الاستغلالالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

الخلاصاتاتصالالخصوصية© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2023-6553 — استغلال إثبات المفهوم وتقرير فني لثغرة CVE-2023-6553، وهي ثغرة تضمين ملفات PHP غير مصادق عليها تتيح تنفيذ تعليمات برمجية عن بُعد في إضافة Backup Migration لووردبريس بإصدار <=1.3.7. | Kitploit
أدوات/GitHubGitHub/dungsocool/cve-2023-6553
تحليل الثغرات الأمنيةتحليل الكودالاستغلالاستغلال تطبيقات الويباختبار الاختراقالتعلم والتعليم
GitHubdungsocool/cve-2023-6553

CVE-2023-6553

استغلال إثبات المفهوم وتقرير فني لثغرة CVE-2023-6553، وهي ثغرة تضمين ملفات PHP غير مصادق عليها تتيح تنفيذ تعليمات برمجية عن بُعد في إضافة Backup Migration لووردبريس بإصدار <=1.3.7.

عرض المستودع
8منذ شهر واحدلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

CVE-2023-6553

تضمين ملفات PHP يؤدي إلى تنفيذ تعليمات برمجية عن بُعد — إضافة Backup Migration

الإضافة: Backup Migration (backup-backup) ≤ 1.3.7

CVSS: 9.8 (حرجة)

CWE: CWE-98 — تحكم غير سليم في اسم الملف لجملة Include/Require

متطلب المصادقة: لا يوجد

الأثر: تنفيذ تعليمات برمجية عن بُعد


1. ما هي هذه الثغرة؟

إضافة Backup Migration هي إضافة ووردبريس شائعة إلى حد ما (أكثر من ~90,000 تثبيت نشط) تساعد المستخدمين على إنشاء نسخ احتياطية. أثناء عملية النسخ الاحتياطي، يوجد في الإضافة ملف باسم backup-heart.php يعمل في الخلفية - يستقبل معلومات الإعداد عبر ترويسات HTTP لمعرفة الدليل الذي يجب نسخه احتياطيًا، وأين يقع ملف الإعداد، وما إلى ذلك.

تكمن المشكلة في أن هذا الملف يثق تمامًا في ترويسات HTTP المرسلة من العميل، ويأخذ قيمة الترويسة مباشرة إلى مسار الملف، ثم يستخدم require_once() لتحميل الملف من ذلك المسار. لا يحتاج المهاجم سوى إرسال ترويسة Content-Dir تشير إلى دليل يحتوي على كود PHP خبيث → يقوم الخادم تلقائيًا بتضمينه وتنفيذه.

من الجدير بالذكر أن ملف backup-heart.php لا يتطلب مصادقة — فهو يتحقق فقط من أن طريقة الطلب هي POST، دون التحقق من أي nonce أو صلاحيات مستخدم. يمكن لأي شخص على الإنترنت إرسال طلب إليه.

⇒ هذه ثغرة بدون نقرة (zero-click).

الخاصيةالقيمة
معرف CVECVE-2023-6553
درجة CVSS9.8 (حرجة)
الإضافةbackup-backup (Backup Migration) ≤ 1.3.7
المصادقةغير مطلوبة
تفاعل المستخدملا شيء (بدون نقرة)
الإصلاحالإصدار 1.3.8

2. المعرفة الأساسية

تضمين الملفات في PHP

توجد في PHP دوال مثل include() و require() و require_once() تُستخدم لتضمين ملفات PHP أخرى في البرنامج الجاري. عندما يأتي مسار الملف المُمرَّر إلى هذه الدوال من مدخلات المستخدم دون تحقق، يمكن للمهاجم إجبار الخادم على تضمين أي ملف يريده:

  • LFI (تضمين الملفات المحلي): تحميل ملف موجود على الخادم — على سبيل المثال، ملف سجل تم "تسميمه" بكود PHP.
  • RFI (تضمين الملفات البعيد): تحميل ملف من خادم خارجي — يتطلب allow_url_include=On (عادةً ما يكون معطلاً افتراضيًا).

تندرج هذه الثغرة تحت LFI — يتحكم المهاجم في المسار المُمرَّر إلى require_once() الذي يشير إلى ملف PHP تمكن المهاجم من كتابته على الخادم.

لماذا تعتبر ترويسات HTTP خطيرة؟

يعتقد العديد من المطورين أن ترويسات HTTP هي بيانات وصفية "داخلية" لا يعرفها سوى الخادم والعميل. في الواقع، يتحكم المهاجمون في 100% من محتوى الترويسات — يمكنهم تعيين أي اسم وقيمة لأي ترويسة. الثقة بالترويسات تشبه تمامًا الثقة بمدخلات النماذج — يجب التحقق منها.

define() وثوابت PHP

تُنشئ define('NAME', $value) ثابتًا يُستخدم في جميع أنحاء التطبيق. وبمجرد تعريفه عبر define، لا يمكن تغيير قيمته. إذا كانت $value قادمة من مهاجم، فكل مكان يستخدم هذا الثابت يتأثر.

3. تحليل الكود المصدري — من أين تنشأ الثغرة؟

الخطوة 1: العثور على نقطة الاستدعاء (Sink)

بدأت باستخدام grep للبحث عن جميع جمل require وinclude في أنحاء الإضافة:

grep -rn "require\|include" includes/

image.png

أعادت نتائج البحث العديد من استدعاءات require/include. وبمراجعتها، كانت معظمها استدعاءات include_once في banner/misc.php وbanner/views/index.php — وهي تخص كود عرض واجهة الإدارة بمسارات ثابتة، مما يجعلها غير قابلة للاستغلال.

غير أن سطرين في backup-heart.php لفتا انتباهي:

includes/backup-heart.php:64:   define('BMI_INCLUDES', BMI_ROOT_DIR . 'includes');
includes/backup-heart.php:118:  require_once BMI_INCLUDES . '/bypasser.php';

يستخدم السطر 118 require_once مع الثابت BMI_INCLUDES — ولو كان هذا الثابت بقيمة ثابتة لكان آمنًا. ولكن بالنظر إلى السطر 64، رأيت أن BMI_INCLUDES مبني من ثابت آخر هو BMI_ROOT_DIR. لذا علينا تتبع المصدر أكثر: أين تُسند قيمة BMI_ROOT_DIR؟

استخدمت grep مرة أخرى لتتبعه:

grep -n "BMI_ROOT_DIR" includes/backup-heart.php

النتائج:

image.png

Line 62: define('BMI_ROOT_DIR', $fields['content-dir']);
Line 64: define('BMI_INCLUDES', BMI_ROOT_DIR . 'includes');

يُظهر السطر 62 أن BMI_ROOT_DIR يأخذ قيمته من $fields['content-dir']. هذا متغير وليس قيمة ثابتة — نحتاج إلى فتح الملف ومعرفة ما يحتويه $fields.

الخطوة 2: فحص الكود المصدري — من أين يأتي $fields؟

فتحت backup-heart.php في VS Code عند السطر 62:

// Line 62
define('BMI_ROOT_DIR', $fields['content-dir']);

// Line 64
define('BMI_INCLUDES', BMI_ROOT_DIR. 'includes');

image.png

من الواضح أن $fields['content-dir'] يدخل مباشرة إلى define(). الآن نحتاج إلى تحديد أين يُسند المتغير $fields:

// Lines 7-9: Only checks POST method
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    exit;
}

// Lines 30-33: Reads ALL HTTP headers from the request
if (isFunctionEnabled('getallheaders')) {
    $fields= getallheaders();
}

// Lines 42-46: Lowercases header names
foreach ($fieldsas $key=> $value) {
    $buffer= $value;
    unset($fields[$key]);
    $fields[strtolower($key)] = $value;
}

image.png

image.png

عند هذه النقطة، يصبح السبب الجذري واضحًا تمامًا: $fields يحتوي على جميع ترويسات HTTP المستخرجة عبر getallheaders() — وهي خاضعة بالكامل للعميل. لا يوجد wp_verify_nonce() ولا current_user_can() ولا فحص للمسار الصحيح — بل يتحقق فقط من طريقة POST ويقرأ الترويسات مباشرة.

الخطوة 3: ملخص مسار الهجوم

Attacker sends POST request with header Content-Dir: /path/to/attacker/
    ↓
getallheaders() reads raw headers → $fields['content-dir'] = "/path/to/attacker/"
    ↓
define('BMI_ROOT_DIR', "/path/to/attacker/")   ← no validation
    ↓
define('BMI_INCLUDES', "/path/to/attacker/includes")
    ↓
require_once "/path/to/attacker/includes/bypasser.php"   ← executes PHP
    ↓
Attacker code runs with www-data privileges → RCE

ملخص السبب الجذري: ترويسة HTTP ← define() ← require_once()، دون أي خطوة تحقق بينها.

الخطوة 4: التصحيح باستخدام Xdebug

استخدمت Xdebug + VS Code لتأكيد مسار الهجوم بصريًا. وضعت نقطتي توقف عند السطرين 62 و118 في ملف backup-heart.php، ثم أرسلت طلب الاستغلال باستخدام curl.

نقطة التوقف 1 — السطر 62:

توقف المُنقّح (debugger) مباشرة عند define('BMI_ROOT_DIR', $fields['content-dir']). عند توسيع المتغير $fields في لوحة Variables ظهرت مصفوفة من 22 عنصرًا — تحتوي على جميع ترويسات HTTP التي أرسلها العميل. وتحديدًا:

  • content-dir = "/tmp/bmi/" — هذه هي القيمة المُرسلة عبر الترويسة تمامًا، والتي تُسند مباشرة إلى الثابت BMI_ROOT_DIR.
  • content-abs = "/var/www/html/", content-configdir = "/tmp/bmi/", content-backups = "/tmp/bmi/back..." — جميعها خاضعة للمهاجم.

لا توجد أي خطوات تحقق أو تصفية تُطبق على content-dir قبل تمريره إلى define().

image.png

نقطة التوقف 2 — السطر 118:

عند الضغط على F5، توقف المُنقّح عند require_once BMI_INCLUDES . '/bypasser.php'. بالنظر إلى الحالة:

  • لوحة Variables: لا يزال $fields يحتفظ بـ content-dir = "/tmp/bmi/" — مما يثبت أن القيمة لم تتغير بين السطرين 62 و118.
  • لوحة Call Stack: تُظهر {main} backup-heart.php 118:1 — أي أن الكود نُفذ مباشرة من أعلى الملف حتى هذه النقطة، متجاوزًا أي برمجيات وسيطة أو فحوصات مصادقة.
  • السطر 118 يستعد لتضمين الملف الموجود في المسار /tmp/bmi/includes/bypasser.php — وهو ملف يتحكم المهاجم في محتواه.

image.png

تنزيل الأداة