الخلاصة
- استطاعت خدمة memcached عبر UDP، حين تكون مكشوفة للإنترنت، أن تستقبل طلباً صغيراً بعنوان ضحية مزوّر وترسل إلى تلك الضحية جواباً أكبر بآلاف المرات.
- توزعت المعالجة بين سلطات محلية: عطل memcached 1.5.6 بروتوكول UDP افتراضياً، ويمكن لشبكة الوصول إسقاط المصادر المنتحلة، واحتفظ GitHub بقرار الرصد وتحويل إعلانات BGP واختيار مسار التنقية.
قبل المضاعفة كانت هناك هوية مستعارة
صُمم memcached ليكون مخبأً سريعاً داخل شبكة تطبيق موثوقة. لا ينشئ UDP اتصالاً قبل إرسال الرد، ولذلك لا يثبت أن العنوان المكتوب في خانة المصدر يخص من أرسل الطلب. عندما تصبح الخدمة متاحة للعامة، يستطيع المهاجم أن يكتب عنوان الضحية ويرغم الخادم على إرسال الرد إليها.
شرحت Cloudflare تسلسلاً عملياً: يضع المهاجم أولاً قيمة كبيرة في مخبأ مكشوف، ثم يرسل أمر get صغيراً مع تزوير عنوان الضحية. في تجربة، أدت 15 بايتاً إلى جواب حجمه 134 كيلوبايت. وفي رصد منفصل، أنتجت 15 بايتاً 750 كيلوبايت، أي نحو 51,200 ضعفاً.
هذه ليست نسبة ثابتة لكل مفتاح أو خادم، وليست قياساً لكل حركة هجوم GitHub. لكنها تكشف توزيع التكلفة: المهاجم يدفع مقابل طلب صغير، ومشغل المخبأ يدفع مقابل خروج كبير، والضحية تستقبل ما لم تطلبه.
يتطلب المسار شرطين معاً: مخبأ يجيب UDP غير الموثوق، وشبكة تسمح بخروج حزمة تحمل عنواناً لا يخص عميلها. إزالة أحد الشرطين تكسر سلسلة الانعكاس.
تسع دقائق في تقرير GitHub
أفاد GitHub بأن موقعه تعذر الوصول إليه من 17:21 إلى 17:26 بالتوقيت العالمي في 28 فبراير/شباط 2018، ثم تعذر بصورة متقطعة حتى 17:30. وقال إن سرية البيانات وسلامتها لم تتعرضا للخطر.
جاءت الحركة من عشرات آلاف النقاط في أكثر من ألف نظام مستقل، وبلغت الذروة 1.35 تيرابت في الثانية و126.9 مليون حزمة في الثانية. هذه أرقام الحادث كما قاسها GitHub، وليست استنتاجاً من تجربة Cloudflare.
عند 17:21 اكتشفت المراقبة خللاً في نسبة الوارد إلى الصادر. وبعد تجاوز الحركة الداخلة عبر ناقل واحد 100 غيغابت في الثانية في أحد المواقع، قرر الفريق تحويل الحركة إلى Akamai. في 17:26، سحب أمر عبر ChatOps إعلانات BGP من مزودي العبور وجعل إعلان AS36459 حصرياً عبر وصلات Akamai. تقاربت المسارات وطبقت قوائم تحكم عند حافة Akamai، ثم أعلن GitHub التعافي الكامل عند 17:30.
في 17:34 سحب GitHub أيضاً مسارات نقاط تبادل الإنترنت لينقل 40 غيغابت إضافية. وبعد الساعة 18:00 بقليل جاءت موجة ثانية بنحو 400 غيغابت. أعلن التقرير نية بحث أتمتة تشغيل مزودي التخفيف لتقليل زمن التعافي؛ النية ليست دليلاً على أن التنفيذ اللاحق تم.
يبين التسلسل حدود سلطة الضحية. لم يستطع GitHub إعادة ضبط عشرات آلاف المخابئ البعيدة أثناء الهجوم. لكنه استطاع قراءة حافته، وتغيير إعلاناته، واختيار شريك، والتأكد من عودة الخدمة.
غير سطرين فتغير الإذن الافتراضي
صدر memcached 1.5.6 في 27 فبراير/شباط. وتقول ملاحظاته إن الغرض الرئيسي كان تعطيل UDP افتراضياً. يوضح الالتزام البرمجي التغيير بدقة: تحولت settings.udpport من 11211 إلى 0، وتوقف تحديد منفذ TCP وحده عن تشغيل منفذ UDP مماثل ضمناً. وتغيرت الاختبارات مع السلوك.
لم يُحذف UDP. كان للمشغل الذي يحتاجه أن يعيد تشغيله صراحة باستخدام -U 11211. لم يفرض المشروع حظراً مركزياً على استعمال محلي مشروع، بل أنهى حالة كان فيها غياب القرار نفسه يمنح خدمة عامة خطرة.
رقم النسخة لا يثبت النتيجة. قد تعيد وسيطة بدء التشغيل فتح UDP، وقد تحمي جدران النار نسخة أقدم مربوطة بعنوان خاص. السؤال القابل للتحقق هو: هل يجيب البرنامج الجاري طلب UDP 11211 من شبكة غير موثوقة، وما حجم ما يرسله؟
هنا تظهر أولوية الكود الجاري. وثيقة الإصدار تعلن القصد، والفرق البرمجي يغير البداية، والاختبار يحميها من التراجع، لكن المقبس الفعلي والمسبار الخارجي والحزمة المرصودة هي دليل التبني.
منع الانتحال قرار عند شبكة المصدر
إغلاق المخبأ يزيل المضاعف. والتحقق من عنوان المصدر يزيل الكذبة التي توجه الرد إلى الضحية.
يوصي RFC 2827، المعروف بـ BCP 38، بأن يرشح مزود الإنترنت حركة عميله بحيث لا يسمح إلا بعناوين المصدر التي يستخدمها العميل بصورة مشروعة. قرب نقطة الوصول، يجب أن تسقط الحزمة التي تخرج من عميل ما وتدعي أنها صادرة عن GitHub.
لكن الشبكات متعددة الارتباط والمسارات غير المتناظرة تحتاج إلى اختيار دقيق. يناقش RFC 3704 قوائم الدخول، والتحقق الصارم من المسار العكسي، والمسار الممكن، وصيغاً أكثر تساهلاً. قد يسقط التطبيق الصارم الخاطئ حركة مشروعة. وقد يثبت التطبيق المتساهل وجود مسار نحو العنوان من دون أن يثبت حق هذا العميل في استخدامه.
تحدد المواصفة الأولية الدنيا الخاصية المشتركة: لا تصدر حافة العميل هوية مصدر لا يملكها. أما الآلية، وتحديث معلومات التوجيه، والاستثناءات، وموعد النشر فقرارات محلية. حرية التنفيذ لا تلغي واجب إظهار النتيجة.
لكل حد إثباته
يثبت مشغل المخبأ حالة الاستماع والجدار الناري ونتيجة الفحص الخارجي وحجم الخروج. وتثبت شبكة الوصول اختبار منع الانتحال وسجلات التدفق. وتثبت الضحية التنبيه وتمرين تحويل BGP وقدرة التنقية والعودة الآمنة.
لا يحل أحدها محل الآخر. التنقية تحمي الضحية بعد أن أرسلت المخابئ البعيدة البيانات. وتعطيل UDP يزيل عاكساً واحداً ولا يصلح شبكة المصدر. وBCP 38 يوقف كثيراً من الطلبات المزورة لكنه لا يبني خطة استمرارية GitHub.
ولا تتطلب هذه الحدود حاكماً دائماً. رشحت Akamai الحركة لأن GitHub اختار ذلك المسار؛ لم تحصل على حق أبدي في تقرير توجيه GitHub. وحدد مشروع memcached بداية أكثر أماناً من دون أن يدير أجهزة المستخدمين. ونسقت RFCs ممارسة من دون تشغيل موجه واحد.
حدود الأدلة
تثبت المصادر آلية التضخيم وذروة GitHub وتغيير الوضع الافتراضي. ولا تثبت أن كل memcached كان مكشوفاً، أو أن كل حزمة تضخمت 51,200 مرة، أو أن كل شبكة مصدر افتقرت إلى BCP 38. كما لا تحول خطة GitHub للأتمتة إلى نشر مؤكد.
الاستنتاج الأدق هو أن الأمان كان سلسلة من حقوق الرفض. رفض البرنامج أن يفتح UDP من دون طلب صريح، ورفضت شبكة المصدر المفترضة الهوية الزائفة حيث طُبق الترشيح، ورفضت الضحية المسار المشبع بسحب إعلانها. الإعلان يصف الحماية؛ السلوك الجاري وحده يثبتها.
المصادر
- GitHub، تقرير حادث DDoS في 28 فبراير
- Cloudflare، Memcrashed
- Cloudflare، السبب الحقيقي لهجمات DDoS الكبيرة: انتحال IP
- ملاحظات إصدار memcached 1.5.6
- التزام memcached الذي عطل UDP افتراضياً
- توثيق إعداد خادم memcached
- RFC 2827 / BCP 38
- RFC 3704 / BCP 84
- Heng Lu، Running-Code Primacy
- Heng Lu، Minimum Initial Specification, Localized Future Decision, and Voluntary Adoption
إحاطة الأعضاء
سياق أعمق للملف الشخصي
سجّل الدخول بمستوى العضوية المناسب لفتح الإحاطة الكاملة وملاحظات المصادر.
للدائرة الاستراتيجية فقط
الدائرة الاستراتيجية
مفتوح لجميع القراء. افتح إحاطات الملف الشخصي بعد الانضمام وتسجيل الدخول.
انضم إلى الدائرة الاستراتيجيةلأعضاء تحالف القيادات فقط
تحالف القيادات
لأصحاب الأصول الفكرية المؤهلين وللإدارة؛ سجّل الدخول للوصول إلى إحاطات التحالف.
انضم إلى تحالف القيادات
