يصل الطلب إلى PHP قبل أن يتدخل متحكم التطبيق
قد يرفض تطبيقك رفع ملف بعد أن يكون PHP قد عالج جزءاً من جسم الطلب. لهذا يتطلب خلل بيئة التنفيذ تحقيقاً مختلفاً عن فحص متحكم رفع غير آمن. في CVE-2026-109618 وCVE-2026-109619، المتداولتين باسم PHP2Shell، السؤال الأساسي هو أين تعبر بيانات الطلب التي يتحكم بها المهاجم حدود الأمان داخل المفسر.
أدرس الحادثة عبر ثلاث طبقات: الإصدار الأمني المؤكد، وسلوك بيئة التنفيذ الظاهر في المصدر، والآلية التي تقترحها تطبيقات إثبات المفهوم التي راجعتها. هذا التقييم مؤرخ في 21 أكتوبر 2026 ويستند إلى تحليل ساكن لـPHP 8.4.4 والأجزاء ذات الصلة من PHP 8.5.4، وتطبيقات إثبات المفهوم، وتقارير وعرض توضيحي مقدم. لم أجرِ إعادة إنتاج مستقلة للاستغلال.
ما الذي أكدته PHP؟
أكد إعلان PHP في 20 أكتوبر وجود ثغرتين حرجتين بتقييم CVSS v4.0 9.2 لكل منهما، وحدد الإصدار الأمني في 21 أكتوبر الساعة 14:00 UTC. يحتفظ الإشعار المسبق الذي راجعناه بقائمة الإصدارات المتأثرة والمصححة والتفاصيل التقنية حتى الإصدار. ولا يذكر بنفسه أرقام CVE أو يحدد تتبع الرفع بوصفه السبب الجذري. ترد المعرفات ووصف RCE في التقارير المرتبطة بالحادثة. [1, 2]
ينسب تقرير Huntress إعادة إنتاج CVE-2026-109618 إلى watchTowr، ويذكر أن Huntress لم تعد إنتاج الثغرات ولم ترصد هجمات مرتبطة بها في بيئات شركائها حتى 20 أكتوبر. ويعرض التسجيل الذي راجعناه آثاراً متسقة مع تنفيذ أوامر وإنشاء ملفات، بما فيها WordPress وDrupal. لم نثبت تطابق تنفيذ أداة العرض الظاهر مع التطبيقات التي راجعناها. تستدعي هذه الملاحظات الاستجابة العاجلة، مع بقاء السبب الدقيق وشروط البيئة بحاجة إلى تحديد. [2]
لماذا يدخل تتبع الرفع في التحقيق؟
يمكن لـPHP حفظ معلومات تقدم الرفع في الجلسة أثناء تحليل طلب multipart. تتضمن الحالة عداد بايتات للطلب كله، وعدادات للملفات، وبيانات وصفية، وعلامات اكتمال. تعمل الميزة داخل معالجة الطلب؛ لذلك لا يصف نموذج الرفع الظاهر في الموقع كامل سطح الهجوم في بيئة التنفيذ. يوثق دليل PHP الميزة وتواتر تحديثها القابل للضبط. [3]
في المصدر المدروس، ينشئ FILE_START حالة الملف، ويحدث FILE_DATA العدادات، وينهي END التتبع أو ينظف بياناته. يُحفظ مؤشر العداد الإجمالي عند الإنشاء الأول، بينما يُحدّث مؤشر الملف الحالي عند كل ملف. تسبق الكتابة إلى العدادات استدعاء دالة تحديث الجلسة. لهذا لا يمكن افتراض أن المصادقة داخل التطبيق تحمي تلقائياً مرحلة التحليل السابقة. أما ضبط الوصول على وكيل قبل وصول الطلب إلى PHP فيفرض الحماية عند حد مختلف. [4]
السلسلة المقترحة مرحلةً مرحلة
يربط أحد تطبيقات إثبات المفهوم التي راجعناها المعرف الأول بعداد البايتات الإجمالي، ويربط تطبيق آخر المعرف الثاني بعداد الملف الحالي. يقترح الاثنان مشكلة مؤشر قديم أثناء تحديثات التقدم المتكررة. هذه نسب واردة في التطبيقات التي راجعناها، وليست خريطة أثبتها إشعار المطور الذي راجعناه. يتطلب تفسيرهما وصول الطلب إلى المسار، وإنشاء حالة التقدم، وتحرير مساحة الذاكرة قبل الوصول اللاحق إليها، ثم تحكماً مؤثراً في الحالة المتضررة.
يتطلب تحويل ذلك إلى RCE أيضاً مسار تنفيذ يمكن بلوغه وعناوين وبنى متوافقة مع البناء المستهدف. يعرض التسجيل مرحلة كشف عناوين؛ أما استخراج الرموز في الإطار المحلي فلا يثبت كشفاً مماثلاً عن بعد. التخصيصات السابقة لا تثبت إعادة استخدام موضع محدد بعد تحريره، وعمليتا إرسال بينهما تأخير لا تثبتان استدعاءين مقابلين على الخادم. هذه شروط منفصلة يجب أن تربطها السلسلة الناجحة؛ والتطبيقات التي راجعناها المتاحة تترك هذا الربط ناقصاً.
سؤال العمر: من ما زال يملك المصفوفة؟
يعني use-after-free الوصول إلى تخصيص ذاكرة بعد انتهاء عمره. لنسمّ مصفوفة التقدم الحية P ومصفوفة الجلسة المفككة بشكل مستقل D. تشابه المحتوى لا يجعلهما تخصيصاً واحداً. في مسار التحديث العادي الناجح في PHP 8.4.4، تزيد الدالة عداد المراجع قبل إدراج P في شجرة الجلسة. تسقط إعادة تهيئة الشجرة مرجعها، بينما تبقى حالة التقدم مالكة لـP. استبدال D لا يحرر P. وتوجد الزيادة المقابلة أيضاً في دالة PHP 8.5.4 المدروسة. [4, 5, 6, 7]
يمثل نموذج الملكية هذا الحلقة غير المحسومة في الشرح المقدم. وهو لا ينفي أياً من الثغرتين ولا يفند العرض المنفصل. يجب أن يحدد تفسير السبب الجذري الكامل مساراً أو شرطاً آخر يكسر ضمان العمر. حتى الفصل في نهاية الطلب يحتاج إلى تحليل الترتيب: عند تعطيل التنظيف تظل شجرة الجلسة القديمة مالكة للمصفوفة الأصلية لحظة الكتابة الأخيرة إلى العداد، قبل التحديث الإجباري والإنهاء. لا يكفي أن يصبح المؤشر قديماً ما لم يحدث وصول لاحق عبره. [4]
تلويث الجلسة يعبر حدوداً مختلفة
تصف دراسة مختبرية لطرف ثالث راجعناها مساراً آخر لتنفيذ الشيفرة: وصول محتوى جلسة يتحكم فيه المهاجم إلى موضع تضمين ملفات داخل التطبيق. يمرر مسار الاختبار المصمم ليكون عرضة لتضمين الملفات معامل طلب مباشرة إلى include(). يعطّل ملف إعدادات اختبار الاحتفاظ بالبيانات تنظيف بيانات التقدم ويغيّر توقيت التحديث وحدود multipart. يورد سجل الاختبار الوارد في الدراسة تنفيذ الشيفرة في هذه الظروف. يوضح ذلك نوع الحدود التي يجب تدقيقها داخل التطبيق، لكنه لا يثبت بصورة مستقلة آلية فساد الذاكرة لأي من الثغرتين.
تورد الدراسة نفسها اختيار معرّف جلسة دون ترويسة Cookie، وتثبيت جلسة ضمن نموذج تسجيل دخول متساهل عمداً، وفشل تسلسل مرتبط بوجود رمز الخط العمودي في مفتاح التقدم. تعتمد هذه الملاحظات على المعالج وآلية التسلسل وسياسة الجلسات وسلوك التطبيق. يجب أن يبقى محتوى الجلسة بيانات؛ وأن تأتي مسارات include/require من قائمة سماح مضبوطة، وأن يتغير معرّف الجلسة عند الانتقال إلى حالة موثقة. وجود سجل تقدم وحده لا يثبت إعادة استخدام تخصيص ذاكرة محرر.
تصف نتيجة uid=0 في السجل هوية عملية المختبر. يشغّل برنامج الإطلاق خادم تطوير PHP دون تحديد مستخدم محدود الصلاحيات؛ لذلك لا تثبت هذه النتيجة تصعيد الصلاحيات أو الوصول إلى root على المضيف. لهذا الفصل أهمية تشغيلية: إصلاح تضمين الملفات غير الآمن وسياسة الجلسات يعالج التعرض على مستوى التطبيق، بينما تظل ثغرة سلامة ذاكرة بيئة التنفيذ بحاجة إلى إصلاح خاص بها من المورّد.
الإصدارات المتأثرة وتوافق الاستغلال سؤالان مختلفان
لا يقدم إشعار المطور الذي راجعناه نطاقاً مؤكداً للإصدارات المتأثرة أو مصفوفة للإصدارات المصححة. تبقى الادعاءات الواسعة التي تشمل PHP بدءاً من الإصدار 5 ضمن التقارير العامة. PHP 8.4.4 هو أساس تحليل المصدر لدينا؛ ويظهر PHP 8.5.4 في المادة المقدمة وأحد ملفات التعريف المعروضة. لا يحدد أي من الأمرين النطاق الكامل. هذه لقطة للأدلة المتاحة، وقرارات الحزم يجب أن تستند إلى نشرة المطور التفصيلية. [1, 8]
قد تشمل الثغرة عدة فروع بينما يدعم استغلال معين معمارية واحدة أو بناء حزمة أو تكاملاً واحداً مع الخادم. كذلك لا يثبت فشل PoC سلامة البيئة. يتضمن العرض ملفات تعريف موصوفة بأنها Apache prefork مع mod_php وPHP-FPM؛ لكنه لا يثبت شمول جميع أنواع SAPI. احصر البناء والتكامل اللذين يعالجان الطلبات فعلياً، بدلاً من استنتاج التعرض من إصدار CMS أو برنامج CLI وحده.
يورد تقرير التجارب الصادر عن الطرف الثالث عدم تنفيذ أوامر خلال محاولات استغلال فساد الذاكرة على php:8.4.4-cli وphp:8.4.4-fpm وphp:8.2.34-fpm، رغم تحديد العناوين محلياً. هذه نتائج أوردها مؤلف التقرير وليست اختبارات أُجريت لهذه المقالة. لا تثبت وجود إصدارات آمنة، ولا تبرر تعميم نجاح مثال تضمين الملفات على تثبيتات PHP الافتراضية. يقترح مؤلف التقرير أيضاً درجة CVSS v3.1؛ وهي تقييم منفصل من المؤلف، وليست تحويلاً لتقييم v4.0 الصادر عن PHP.
أي إعدادات تغيّر الشروط؟
في المسار المقترح، يتحكم session.upload_progress.enabled بالتتبع؛ ويحدد name حقل التفعيل؛ ويضبط freq وmin_freq عتبات التحديث؛ ويتحكم cleanup بإزالة معلومات التقدم بعد معالجة POST. تؤثر معالجات الجلسة والتسلسل في حفظ الحالة. تحدد هذه الإعدادات ما ينبغي فحصه، ولا تشكل قائمة شروط مؤكدة للثغرتين. وبالأخص لا يمكن افتراض أن التنظيف اللاحق يمنع خطأ ذاكرة وقع قبله. [3, 9]
تؤثر SAPI والتخزين المؤقت على الخادم وحدود جسم الطلب والمهل في توقيت وصول البيانات إلى المحلل. قد لا تبقى وقفة العميل وقفة بين استدعاءات PHP بعد التخزين المؤقت. افحص الإعدادات الفعلية لعملية الويب ولكل مجمع FPM؛ فقد تختلف إعدادات CLI. إذا لم تكن هناك حاجة لتتبع الرفع، قيّم تعطيله كتقوية وقائية. لا تثبت الأدلة المدروسة أن هذا التغيير حل مؤقت كامل لأي من الثغرتين. [3, 9]
تكشف إعداد المختبر الذي راجعناه أيضاً تفصيلاً مهماً في الإعدادات: تضبط session.upload_progress.freq=1 فاصلاً مطلقاً بالبايت، بينما تتناسب القيمة 1% مع حجم الطلب. يستخدم ملف إعدادات اختبار فساد الذاكرة القيمة الأولى رغم أن التعليقات تصف إعدادات افتراضية. ويضبط ملف إعدادات اختبار الاحتفاظ بالبيانات القيمتين cleanup=0 وmin_freq=0. قارن القيم الفعلية ووحداتها قبل تعميم نتائج هذه البيئات التجريبية على الإنتاج. [4, 9]
نطاق الضرر تحدده صلاحيات العملية
قد يكفي التنفيذ بهوية www-data لاختراق التطبيق. بحسب الصلاحيات، تستطيع العملية قراءة بيانات اعتماد قاعدة البيانات أو تعديل محتوى قابل للكتابة أو الوصول إلى خدمات خلفية. قد توسع الهويات الخدمية والمجلدات المشتركة الأثر إلى تطبيقات أخرى. هذه نتائج يجب تقييمها في البيئة، وليست ادعاءً بأن كل أثر وقع في العرض. السؤال المفيد هو ما الذي تستطيع العملية قراءته وتغييره والوصول إليه.
توصي Huntress بمراقبة العمليات الفرعية غير المتوقعة لعمليات PHP وخادم الويب. اربط سلسلة العمليات بالطلبات والتوقيت والملفات الجديدة والاتصالات الصادرة؛ فالتطبيقات المشروعة تشغّل أدوات أيضاً، وقد يحدث التنفيذ دون إطلاق صدفة جديدة. وتوضح فحوص الملفات القديمة في المشغل المحلي ومعالجة FastCGI الناقصة في الإطار لماذا يجب ربط نتيجة الأداة بالحدث. مثال Huntress عن حادثة PHP سابقة كان غير مرتبط صراحةً بـPHP2Shell، فلا يصح عرضه كاستغلال لهاتين الثغرتين. [2]
تحقق من الإصلاح حيث تُعالج الطلبات فعلياً
اربط العناوين العامة بحزم PHP أو صور الحاويات التي تخدمها، وبـSAPI والإضافات والإعدادات الفعلية. أدرج برامج الموردين وبيئات الاستضافة التي تتضمن PHP. طابق النشرة التفصيلية مع حزم التوزيعة أو المورد، مع مراعاة الإصلاحات المنقولة إلى إصدارات أقدم. استبدل العمليات المتأثرة أو أعد تشغيلها، ثم تحقق من أن البناء المصحح يعالج الحركة. ضع خطة ترقية أو تقليل تعرض للبيئات التي لا تتلقى تحديثات أمنية مدعومة.
الهدف التقني هو وصل العملية الضعيفة بشروط الوصول إليها وبالكود الذي يعيد ضمان السلامة المطلوب. النتيجة النظيفة لتطبيقات إثبات المفهوم هذه لا تعوض ذلك الربط. في التحقق من الإصلاحات، أتتبع الادعاء إلى العملية المنشورة وأتحقق من أن الإصلاح المعني يعمل فعلياً. إذا احتاجت بيئة PHP لديك إلى هذا التقييم، يبدأ العمل بالبيئة العاملة والأدلة القابلة للفحص.
المصادر
- [1] PHP: الإعلان المسبق عن الإصدار الأمني
- [2] Huntress: تقرير PHP2Shell (النص المقدم)
- [3] دليل PHP: تقدم الرفع في الجلسة
- [4] PHP 8.4.4: استدعاءات الجلسة وملكية الذاكرة
- [5] PHP 8.4.4: عمليات جدول التجزئة
- [6] PHP 8.4.4: الإتلاف بعد تناقص المراجع
- [7] PHP 8.5.4: تنفيذ الجلسات
- [8] watchTowr: أسئلة PHP RCE
- [9] دليل PHP: إعدادات الجلسة
هل تحتاج إلى هذا الفحص في منتجك؟
المعالجة والتحقق من الإصلاحاتهل تريد أن تتعلم اكتشاف ثغرات كهذه بنفسك؟
دورة مراجعة الكود الأمني بتدريب فردي