رجوع

2026/10/28

Node2Shell (CVE-2026-111497): ما الأنظمة المعرّضة للخطر، وما الذي يجب فعله الآن

ما الأنظمة التي تكشفها فعلًا ثغرة CVE-2026-111497 في Brotli، ومدى إلحاح كل حالة، وخطوات الترقيع وإعادة البناء وإعادة التشغيل والتخفيف الآن.

آخر تحديث: 27 أكتوبر 2026

الثغرة CVE-2026-111497، المعروفة باسم “Node2Shell” أو “HTTP2Shell”، هي خلل في إفساد الذاكرة داخل أداة فك ضغط Brotli. وBrotli هو أسلوب الضغط br المستخدم على نطاق واسع في الويب. يقع الخلل في مكتبة Brotli من Google في الإصدارات من 1.0.3 حتى 1.2.0 [1]. تتضمّن Node.js هذه المكتبة، وقد صنّف مشروع Node.js المشكلة بدرجة عالية (High) للفروع 22.x و24.x و26.x [2]. ويُشحن مفكّك الترميز نفسه ضمن حزم Python ومكتبات نظام Linux وتطبيقات سطح المكتب وأدوات المطوّرين، لذا فإن نطاق التعرّض الفعلي أوسع بكثير من “خوادم Node.js”.

هذا المقال موجّه إلى الفرق التي تحتاج إلى أن تقرّر بسرعة ما إذا كانت معرّضة للخطر وما الذي ينبغي فعله أولًا.

الخلاصة: إذا كان أيٌّ من أنظمتك يفكّ ضغط بيانات Brotli واردة من جهة لا تتحكم بها (عميل على الإنترنت، أو موقع ويب خارجي، أو مُرسِل webhook، أو ملف مرفوع)، فتعامل مع الأمر على أنه عاجل. طبّق الترقيعات، وأعد البناء، وأعد التشغيل، واحظر br في هذه الأثناء.

ما الذي تفعله الثغرة

يُسيء مفكّك الترميز معالجة “تبديل كتلة” (block switch) مشوّه في تدفق البيانات المضغوطة. فهو يعامل الخطأ على أنه “أحتاج إلى مزيد من المدخلات” بدلًا من “هذه البيانات غير صالحة”، ويواصل إلحاق البايتات بمخزن مؤقت داخلي صغير ثابت الحجم حتى يكتب متجاوزًا نهايته [2]. ويستطيع المهاجم الذي يتمكّن من دفع تطبيقك إلى فك ضغط تدفق Brotli مُعَدّ خصيصًا أن يُفسد ذاكرة العملية. وقد يؤدي ذلك إلى:

  • انهيار (حجب الخدمة). وهذه هي النتيجة الأكثر موثوقية.
  • تسرّب ذاكرة العملية. قد تكشف الاستجابات أو السجلات أجزاء من الأسرار أو الرموز المميزة (tokens) أو بيانات مستخدمين آخرين.
  • احتمال تنفيذ التعليمات البرمجية عن بُعد. تُدرج Node.js تنفيذ التعليمات البرمجية عن بُعد (RCE) ضمن التأثيرات المحتملة [2]. لم يحقق أول إثبات مفهوم علني تنفيذ التعليمات البرمجية إلا على نسخة أُضعفت عمدًا، لكن الباحثين أفادوا منذ ذلك الحين بتحقيق تنفيذ غير موثوق للتعليمات البرمجية على نسخة رسمية غير معدّلة من Node.js 24.22.0 [3].

لا حاجة إلى أي مصادقة: يكفي أن يوصل المهاجم بايتات تصل إلى مفكّك الترميز. ولهذا تبلغ درجة CVSS 4.0 قيمة 9.2 (حرجة) [1]. لذلك فالسؤال الأساسي لكل نظام ليس “هل نستخدم Brotli؟” بل “هل يستطيع طرف غير موثوق أن يجعلنا نفكّ ضغط Brotli؟”

حالات الاستخدام الشائعة ومخاطرها

الحالة 1: واجهات API المكشوفة على الإنترنت التي تقبل أجسام طلبات مضغوطة (الأولوية القصوى)

تفكّ بعض خوادم API المبنية على Node.js، وطبقات BFF، وبوابات API، ونقاط نهاية الرفع ضغطَ أجسام الطلبات المُرسلة مع Content-Encoding: br. ويفعل غيرها الشيء نفسه عبر البرمجيات الوسيطة (middleware). الخطر: يستطيع أي عميل مجهول على الإنترنت إرسال جسم طلب مُعَدّ خصيصًا. وتتراوح الآثار بين إسقاط الخدمة مرارًا، وهو هجوم حجب خدمة زهيد التكلفة، وتسريب الذاكرة من عملية تحتفظ ببيانات الجلسات ومفاتيح API. درجة الإلحاح: طارئة. طبّق الترقيع اليوم، واحظر أجسام الطلبات بترميز br على حافة الشبكة إلى أن تنتهي من ذلك.

الحالة 2: الخدمات التي تجلب محتوى من الخارج (أولوية عالية)

تُجري مستهلكات webhook، وبرامج الزحف والكشط، وخدمات معاينة الروابط وRSS، وتكاملات الدفع أو SaaS، ووكلاء الذكاء الاصطناعي الذين يتصفّحون الويب، جميعها طلبات HTTP صادرة. ويرسل كثير من عملاء HTTP الترويسة Accept-Encoding: br ويفكّون ضغط الاستجابة تلقائيًا. في Python، تفعل urllib3 وrequests ذلك متى كانت الحزمة Brotli أو brotlicffi مثبّتة، حتى لو لم تستوردها شيفرتك أبدًا. وتفعل aiohttp الشيء نفسه، وكذلك httpx عند تثبيتها مع إضافة brotli الاختيارية [4]. الخطر: يمكن لخادم بعيد خبيث أو مخترَق أو منتحَل أن يهاجم الواجهة الخلفية لديك عبر استجابته. ولا يحتاج المهاجم إلى الوصول إلى شبكتك إطلاقًا: فأنت من يتصل به. درجة الإلحاح: عالية. ابدأ بالترقيع حيثما كانت الوجهات غير موثوقة بالكامل.

الحالة 3: تطبيقات سطح المكتب ووكلاء البرمجة بالذكاء الاصطناعي وأدوات سطر الأوامر ذات بيئة التشغيل المضمّنة

تحمل تطبيقات Electron، وأدوات سطر الأوامر المبنية على Bun أو Node، وأدوات المطوّرين المعتمدة على الذكاء الاصطناعي نسختها الخاصة من بيئة التشغيل. ولا يؤدي تحديث حزمة النظام node إلى إصلاحها. كما أن تحديث التطبيق على القرص لا يُصلح النسخ قيد التشغيل بالفعل: فالعمليات طويلة الأمد تُبقي بيئة التشغيل القديمة في الذاكرة إلى أن يُعاد تشغيلها. الخطر: غالبًا ما تحتفظ هذه الأدوات ببيانات اعتماد وتجلب محتوى خارجيًا، ما يجمع الحالة 2 مع عملية ذات صلاحيات مرتفعة. درجة الإلحاح: عالية للأدوات التي تجلب محتوى غير موثوق. حدّثها، ثم أعد تشغيلها فعليًا. وقد تناولنا فخّ “تم التحديث لكن الشيفرة القديمة لا تزال تعمل” بالتفصيل في HTTP2Shell: لماذا لا يعالج تحديث الملف التنفيذي العمليات قيد التشغيل.

الحالة 4: صور الحاويات ومخرجات CI/CD

لا تزال الصور المبنية FROM node:22 أو node:24 أو node:26 قبل الإصلاح تحتوي على بيئة التشغيل المعرّضة للثغرة، حتى لو كان المضيف مُرقّعًا. وينطبق الأمر نفسه على حزم wheel الخاصة بـ Python المضمّنة والتبعيات المُدمجة في المشروع (vendored). الخطر: تعود الشيفرة المعرّضة للثغرة مع كل عملية نشر وكل حدث توسّع تلقائي إلى أن يُعاد بناء الصورة. درجة الإلحاح: عالية للصور التي تقف خلف الحالتين 1 و2. أعد البناء بدلًا من الاكتفاء بإعادة التشغيل.

الحالة 5: مكتبات نظام Linux والخطوط ومعالجة الصور

تشحن التوزيعات مفكّك الترميز كمكتبة مشتركة، مثل libbrotli1 على Ubuntu/Debian. ويستخدمه curl وlibcurl عند تفعيل الضغط، وFreeType لخطوط الويب WOFF2، وبشكل غير مباشر أدوات معالجة الصور والمستندات مثل Pillow. الخطر: يمكن أن تصل بيانات Brotli غير الموثوقة إلى الأنظمة التي تعرض خطوطًا أو مستندات يرفعها المستخدمون، أو التي تجلب محتوى خارجيًا باستخدام curl --compressed. أما الخادم الذي لا يمرّر أبدًا بيانات خارجية إلى هذه المكتبات فتعرّضه العملي منخفض. درجة الإلحاح: متوسطة في معظم الحالات، لكنها عالية لخدمات عرض المستندات أو معالجة الملفات المرفوعة. وقد نشرت Ubuntu حزم brotli مُصلَحة للإصدارات 22.04 و24.04 و26.04 و26.10 [1]. أما بالنسبة إلى RHEL وOracle Linux والتوزيعات الأخرى، فراجع النشرة الأمنية لدى المورّد الخاص بك بشأن حزمة brotli بدلًا من افتراض حالتها.

الحالة 6: الأنظمة الداخلية فقط ذات المدخلات الموثوقة (أولوية أدنى)

تفكّ بعض الخدمات ضغط Brotli فقط من بيانات تنتجها أنت بنفسك، مثل ذاكرات التخزين المؤقت الداخلية أو مخرجات البناء الخاصة بك. وهذه أقل خطورة، لكن خطرها ليس معدومًا: فالمهاجم الذي حصل بالفعل على موطئ قدم يمكنه استغلال الخلل للتوغّل أكثر. درجة الإلحاح: طبّق الترقيع في الدورة الاعتيادية التالية.

ما الذي يجب فعله: خطوات الاستجابة

الخطوة 1: حدّد أين يتم فك ترميز Brotli (اليوم)

  • Node.js: تحقّق من node -v على كل مضيف، وفي كل صورة حاوية وكل مُشغّل CI. وابحث في الشيفرة والإعدادات عن brotliDecompress وcreateBrotliDecompress والبرمجيات الوسيطة لتحليل أجسام الطلبات التي تفكّ ضغط br.
  • بيئات التشغيل المضمّنة: أعدّ قائمة بتطبيقات Electron وأدوات سطر الأوامر المبنية على Bun/Node ووكلاء الذكاء الاصطناعي المستخدمة، وسجّل إصدار بيئة التشغيل المضمّنة في كلٍّ منها، لا إصدار التطبيق فقط.
  • Python: نفّذ pip show Brotli brotlicffi في كل بيئة وصورة. وابحث عن httpx[brotli] والتبعيات المسحوبة بشكل غير مباشر في ملفات القفل (lockfiles) وقوائم SBOM.
  • حزم نظام التشغيل: dpkg -l | grep brotli أو rpm -qa | grep brotli، ثم تحقّق من العمليات التي تحمّل المكتبة فعليًا.
  • رتّب الأولويات وفق الحالات المذكورة أعلاه: كل ما يمكن أن تصل إليه مدخلات غير موثوقة (الحالات 1 و2 و3، و5 مع الملفات المرفوعة) يأتي أولًا.

الخطوة 2: رقّع المكوّنات المتأثرة

  • Node.js: رقِّ إلى 22.23.4 أو 24.22.1 أو 26.12.1 أو أحدث [2].
  • Python: Brotli>=1.2.1 أو brotlicffi>=1.2.1.0. وأعد توليد ملفات القفل [4].
  • Brotli الأصلية (upstream) / شيفرة C المُدمجة في المشروع: 1.0.10 أو 1.1.1 أو 1.2.1، بحسب الفرع [1].
  • حزم نظام التشغيل: طبّق التحديث الأمني الخاص بتوزيعتك لحزمة brotli / libbrotli.
  • تطبيقات سطح المكتب والوكلاء: حدّث إلى إصدارات المورّد التي تنصّ صراحةً على تضمين بيئة التشغيل المُصلَحة. وإذا لم ينشر المورّد شيئًا، فاعتبر التطبيق غير متحقَّق منه بدلًا من اعتباره آمنًا.

الخطوة 3: أعد البناء وأعد النشر وأعد التشغيل

  • أعد بناء صور الحاويات من صور أساسية مُرقّعة وأعد نشرها. فإعادة تشغيل صورة قديمة لا تفيد.
  • أعد تشغيل كل عملية طويلة الأمد كانت قد حمّلت المكتبة المعرّضة للثغرة: خدمات Node، والعمّال (workers)، وجلسات الوكلاء، وكل ما هو مرتبط بمكتبة النظام. وبالنسبة إلى المهام ذات الحالة ووكلاء الذكاء الاصطناعي، أفرغ العمل الجاري أو سلّمه أولًا حتى لا تفقد الأحداث أو الموافقات المنتظرة في قائمة الانتظار.

الخطوة 4: خفّف المخاطر أثناء الترقيع

  • الاتجاه الوارد: ارفض أجسام الطلبات التي تحتوي ترويسة Content-Encoding فيها على br عند الوكيل العكسي أو موازن الأحمال أو WAF، قبل أن يراها أي مفكّك ترميز.
  • الاتجاه الصادر: لا تكفي إزالة br من Accept-Encoding وحدها، لأن الخادم الخبيث يمكنه إرسال br على أي حال. لذا ارفض أيضًا الاستجابات التي تصل مع Content-Encoding: br أو امتنع عن فك ترميزها [4].
  • حل بديل في Python: حيثما يتعيّن تأجيل الترقية، أزل تثبيت Brotli وbrotlicffi حتى يتوقف العملاء عن فك ترميز br. اختبر ذلك أولًا، لأن بعض الخوادم ستظل ترسل br.

الخطوة 5: تحقّق، وراقب مؤشرات الاستغلال

  • تأكّد من إصدار بيئة التشغيل من داخل العملية أو الحاوية قيد التشغيل، لا من مدير الحزم فقط.
  • أعد فحص الصور وقوائم SBOM للتأكد من عدم استمرار سحب أي نسخة أقدم بشكل غير مباشر.
  • راجع السجلات الحديثة بحثًا عن انهيارات غير مبرّرة، أو أخطاء تجزئة (segmentation faults)، أو حلقات إعادة تشغيل في الخدمات التي تعالج br. وتستحق مجموعة من الانهيارات الصادرة عن مصدر واحد التحقيق فيها بوصفها محاولة هجوم.
  • إذا انهارت خدمة عالية التعرّض بشكل غير متوقع قبل ترقيعها، ففكّر في تدوير الأسرار التي كانت تحتفظ بها تلك العملية، إذ لا يمكن استبعاد كشف محتوى الذاكرة.

الملخّص

الوضعالخطرالإجراء
واجهة API عامة تفكّ ترميز أجسام طلبات brحرجرقّع الآن؛ واحظر br على حافة الشبكة
واجهة خلفية تجلب عناوين URL خارجية أو webhooks أو صفحات ويبعالٍرقّع الآن؛ وارفض استجابات br
تطبيقات Electron أو وكلاء ذكاء اصطناعي أو أدوات سطر أوامر ذات بيئة تشغيل مضمّنةعالٍحدّث وأعد تشغيل كل نسخة قيد التشغيل
صور حاويات قديمة ومخرجات CIعالٍأعد البناء من صور أساسية مُرقّعة وأعد النشر
مكتبة نظام مستخدمة للملفات المرفوعة أو الخطوط أو curl --compressedمتوسط–عالٍطبّق تحديث نظام التشغيل؛ وأعد تشغيل الخدمات التي تحمّلها
بيانات داخلية موثوقة فقطمنخفض–متوسطرقّع في الدورة التالية

ترقيع الحزمة ليس سوى نصف المهمة. ولا يزول التعرّض إلا عندما لا تبقى أي عملية قيد التشغيل أو صورة أو بيئة تشغيل مضمّنة قادرة على فك ترميز بيانات Brotli غير موثوقة باستخدام الشيفرة القديمة.

المراجع