لماذا يهم هذا#
ما إن يشترك أكثر من نظام في إرسال رسالة (أداة رحلات تستدعي واجهة مراسلة، أو مكتب دعم يرسل نيابةً عن عميل، أو تكامل شريك يتصرف لعملائه)، حتى يسأل أحدهم في النهاية: من فوّض هذه الرسالة، ولحساب من، وهل كان ذلك الإذن لا يزال سارياً؟ فإن كان مفتاح الواجهة المشترك هو بيانات الاعتماد الوحيدة في الصورة، فلا أحد يستطيع الإجابة. تشرح هذه المادة الثغرة، ولماذا تظهر، والأنماط الراسخة في عالم الأمن الأوسع التي تسدّها. وهي تهم المشترين بقدر ما تهم البنّائين: فطريقة تعامل المزوّد مع هذا تخبرك كثيراً عن مدى أمان ربطه بكل شيء آخر.
انظر إلى بيانات الاعتماد التي تُصدرها منظومة مراسلتك. على الأرجح هناك مفتاح واجهة لكل حساب، وربما نطاقات عليه. وهذا يغطي "يجوز لهذا التطبيق الإرسال".
ولا يغطي السؤال الذي ينشأ فعلاً في أي نظام متكامل: نيابةً عمّن، ولأي مدة؟
لماذا توجد الثغرة#
لأنها لم تكن تهم حين كانت المنصة تُستدعى من خادم واحد يخص شركة واحدة. فالمفتاح كان هو الهوية، وجواب "نيابةً عمّن" كان "صاحب الحساب، بداهةً".
ويتوقف ذلك عن كونه بداهة لحظة وجود أي طبقات. فمحرك رحلات يستدعي واجهة مراسلة لأحد عملائه. ومكتب وكلاء يرسل نيابةً عن المستأجر الذي يخدم طابوره. وتكامل شريك يتصرف لعميل يستطيع إلغاء ذلك الترتيب.
وفي كل حالة تقول بيانات الاعتماد من المتصل. ولا شيء يقول لحساب من يتصل.
حُلّت هوية المستخدم أولاً لأن الضغط كان ظاهراً: فالمستخدمون كثر ويغادرون ويقعون ضحايا التصيّد، والإخفاق يصنع عناوين صحفية. وأنتج ذلك الضغط OAuth و OpenID Connect و SAML. ولم يكن لهوية الخدمة مثل ذلك الضغط. فالخدمات قليلة وداخلية، والسر المشترك يعمل، حتى يصير في أحد عشر موضعاً، أحدها خط بناء لا يملكه أحد.
لمن الاستدعاء، أثناء انتقاله
- 01العميل النهائي
يفوّض شريكاً بالتصرف نيابةً عنه
لا شيء في بيانات الاعتماد يسجّل ذلك
- 02تكامل الشريك
يستدعي بمفتاح مشترك
المفتاح يقول من يستدعي
- 03محرك الرحلات
يستدعي واجهة المراسلة لعميله
ما زال يقول من يستدعي فقط
- 04واجهة المراسلة
ترى مفتاحاً صالحاً — ولا شيء عمّن تُرسل الرسالة لأجله
ما الذي يسوء بدونها#
السحب كل شيء أو لا شيء. فوصول الشريك مفتاح مشترك. وسحب تفويض عميل واحد يعني تدوير بيانات اعتماد يستخدمها كل الآخرين أيضاً.
التدقيق يجيب السؤال الخطأ. فالسجلات تدوّن أي مفتاح أرسل رسالة. وإعادة بناء أي عميل نهائي فوّض ذلك تعني ربط سجلات تطبيق قد لا تكون محفوظة.
نطاق الضرر هو الحساب كله. فمفتاح تكامل مسرَّب يستطيع الإرسال باسم كل من يخدمهم التكامل.
تطبيق الموافقة يقع في المكان الخطأ. فالنظام الذي يحمل سجل الموافقة غالباً ليس النظام الذي يحمل بيانات الاعتماد. وبلا طريقة لقول "أنا أتصرف لهذا الشخص"، يجب الوثوق بالمتصل في الفحص، ما يعني أنه ليس فحصاً.
غياب هوية الخدمة لا يعلن عن نفسه. بل يظهر كسلسلة تنازلات صغيرة، كل منها معقول وحده.
كيف يصير السر المشترك حادثة
- 01مفتاح واحد لتكامل واحد
سليم تماماً. وهو محدود النطاق مصادفةً لأن المتصل واحد.
- 02متصل ثانٍ يستعيره
لا أحد يريد تشغيل عملية التزويد مرتين. والمفتاح صار مشتركاً.
- 03المفتاح يكتسب نطاقاً
يحتاج فعل المزيد فيُمنح المزيد. ولا شيء يسحب ما لم يعد يحتاجه.
- 04التدوير يصير مستحيلاً
فتدويره يعني تنسيق كل حامل، ولا أحد يعرف من يحمله.
- 05يُخترق أحد الحاملين
فيصير كل ما يستطيعه المفتاح متاحاً، ولا تعرف أي حامل فعل ماذا.
أربعة إخفاقات ينتجها المفتاح المشترك
- السحب كل شيء أو لا شيء
سحب صلاحية عميل واحد يعني تدوير مفتاح يستخدمه الجميع
- التدقيق يجيب عن السؤال الخطأ
يسجّل أي مفتاح، لا أي عميل فوّض الرسالة
- نطاق الضرر هو الحساب كله
المفتاح المسرّب يرسل باسم أي أحد يخدمه التكامل
- فرض الموافقة يقع في المكان الخطأ
الفحص يُترك للمستدعي، فلا يكون فحصاً
شكل الجواب#
النمط راسخ خارج هذه الفئة، وأقل تطبيقاً داخلها.
| مفتاح واجهة مشترك طويل العمر | رمز مفوَّض قصير العمر | |
|---|---|---|
| العمر | أشهر أو سنوات | دقائق أو ساعات |
| يقول من المتصل | عادةً | نعم |
| يقول لحساب أي عميل | لا | نعم، كادعاء صريح |
| النطاق | غالباً "كل ما يستطيعه هذا الحساب" | قدرة واحدة وجمهور واحد وقناة واحدة |
| سحب عميل واحد | تدوير المفتاح للجميع | سحب ذلك المنح وحده |
| إن تسرّب | يعمل حتى يلاحظ أحد | ينتهي من تلقاء نفسه |
| أثر التدقيق | أي مفتاح أرسل | أي منح، ولحساب من، ومن أصدره |
وعملياً يعني ذلك:
- رمز قصير العمر لا مفتاح طويل العمر. دقائق، يُحصل عليه مقابل بيانات اعتماد دائمة. فالرمز المسرَّب ينتهي؛ والمفتاح المسرَّب يجب أن يُكتشف.
- ادعاء موضوع صريح. يقول الرمز لأي عميل نهائي هذا الإجراء. ويفرضه النظام المستقبل بدل الوثوق بوسيط في جسم الطلب.
- نطاقات تسمّي القدرة والجمهور. "يجوز إرسال رسائل خدمية، للمستأجر س، على القناة ص"، لا "يجوز استخدام واجهة المراسلة".
- مسار سحب ليس تدويراً. فسحب تفويض واحد يجب ألا يمس أي تفويض آخر.
- سجل تدقيق يحمل سلسلة التفويض، فيكون لسؤال "من فوّض هذه الرسالة؟" جواب مخزّن لا تحقيق.
ولا شيء من هذا يحتاج اختراعاً. فتبادل الرموز في OAuth 2.0 (RFC 8693) يصف كيف تحصل خدمة على رمز للعمل نيابةً عن طرف آخر؛ ورموز JSON Web Tokens (RFC 7519) تحمل ادعاءات موقّعة قابلة للتحقق؛ و TLS المتبادل مع الرموز المربوطة بالشهادة (RFC 8705) يربط الرمز بالعميل الذي يقدّمه؛ وأطر هوية أحمال العمل مثل SPIFFE تعطي كل خدمة هوية قابلة للتحقق بلا أسرار مشتركة. وإرشادات "انعدام الثقة" مثل NIST SP 800-207 تصف المبدأ نفسه على مستوى البنية كلها.
ما يجب أن تكونه بيانات اعتماد الخدمة
- قابلة للتحقق
يستطيع المتلقي فحصها دون استدعاء المُصدِر. توقيع على مفتاح معروف لا استعلام.
- محددة النطاق
تسمّي الإجراءات والموارد. وبيانات تقول "موثوق" لا تقول شيئاً نافعاً.
- قصيرة الأجل
دقائق أو ساعات. والانتهاء هو الخاصية التي تجعل الاختراق محتملاً بلا تنسيق.
- قابلة للنسبة
تعرّف الخدمة المتصلة لا مجرد واقعة التفويض. فالسجلات تحتاج فاعلاً.
- قابلة للسحب
باستقلال، من المُصدِر، بلا تعاون الحامل. وإلا فالثقة دائمة.
- قابلة للتفويض
يعمل أ نيابةً عن ب بإثبات، ضمن نطاق ب ولا يتجاوزه أبداً. وهذا ما يحتاجه الاتحاد.
ما تسأل عنه المزوّد#
إن كنت تشتري لا تبني، فهذه الأسئلة تكشف إلى أي حد تدعم المنصة هذا:
- هل أستطيع إنشاء بيانات اعتماد محصورة في حساب فرعي واحد أو قناة أو قدرة واحدة؟
- هل تدعمون رموزاً قصيرة العمر، وهل أستطيع سحب واحد منها دون تدوير البقية؟
- حين يتصرف شريك أو موزّع نيابةً عني، هل يُظهر سجل التدقيق أي طرف تصرف وبأي سلطة؟
- هل أستطيع رؤية سجلات التدقيق تلك وتصديرها والاحتفاظ بها؟
منصات كثيرة تدعم الحسابات الفرعية والمفاتيح محددة النطاق؛ وأقل منها تدعم التفويض مع السحب لكل عميل. ومعرفة ما تحصل عليه تجنّبك المفاجآت.
لماذا يستحق الفعل قبل الحاجة#
لأن تركيبه لاحقاً صعب. فمتى وُجدت تكاملات تفترض مفتاحاً طويل العمر بسلطة ضمنية، وجب تغييرها كلها، ويملك كلاً منها فريق مختلف بجدول مختلف. والترحيل ليس صعباً تقنياً. بل صعب تنظيمياً، ويستغرق وقتاً طويلاً.
والحجة المضادة واحدة دائماً: لدينا ثلاث خدمات ونعرف من هي، وهذه هندسة زائدة.
وقد تكون هندسة زائدة لثلاث خدمات. لكنها مناسبة تقريباً للرابعة، التي كثيراً ما تكون شريكاً لا فريقاً، ويصعب جداً تركيبها للحادية عشرة، لأن السر المشترك يكون حينها جزءاً حاملاً في عدة خطوط نشر.
الهوية المفوَّضة، بحسب عدد التكاملات
- 1ثلاث خدمات
نعرف من هي
- 2الرابعة
مناسبة تقريباً — وكثيراً ما تكون شريكاً لا فريقاً
- 3الحادية عشرة
السر المشترك جزء حامل في عدة خطوط نشر
المقايضات#
الرموز قصيرة العمر تضيف أجزاء متحركة: خدمة رموز يجب أن تكون متاحة، وتزامن الساعات، وأوضاع فشل أكثر تحتاج مراقبة. والنطاقات الدقيقة تحتاج من يصممها ويصونها. ولشركة واحدة بخادم واحد ومزوّد مراسلة واحد، قد يكون مفتاح واجهة محمي جيداً ويُدوَّر بانتظام بنطاق محدود كافياً تماماً. وتقوى الحجة للتفويض مع كل طرف إضافي يتصرف نيابةً عن غيره.
الصلة بالاتحاد#
إن كنت تدير عدة أنظمة يستدعي بعضها بعضاً بدل نظام مدموج واحد، فهذه هي الطبقة التي تجعل ذلك آمناً. فالعقود المنشورة تتيح للأنظمة التحدث. والهوية بين الخدمات هي ما يجعله قابلاً للدفاع حين يسأل أحدهم ماذا كان مسموحاً لنظام أن يفعل، ولحساب من، ومتى انتهى ذلك الإذن. والاتحاد بدونها مجموعة أسرار مشتركة في ملفات إعداد: مركزية بخطوات زائدة وبلا شيء من العزل الذي كان يُفترض أن تشتريه.
الخلاصة#
أعطِ كل خدمة هوية قابلة للتحقق. وأصدر بيانات اعتماد محددة النطاق قصيرة الأجل قابلة للسحب بدل أسرار مشتركة طويلة الأجل. واجعل التفويض صريحاً وقابلاً للإثبات. وافعل ذلك وعدد التكاملات صغير، فسبب فعله يصل مع أول شريك، وسهولة فعله تغادر بعد ذلك بقليل.
إلى أين بعد ذلك#
- اتحاد الأنظمة دون دمجها: البنية التي تدعمها طبقة الهوية هذه.
- تقييم عقد منصة اتصال: الأسئلة التعاقدية التي تقترن بالأسئلة التقنية أعلاه.
المصادر
كل ادعاء يستحق التحقق، مع مكان للتحقق منه.
- RFC 8693: OAuth 2.0 Token ExchangeIETF
- RFC 7519: JSON Web Token (JWT)IETF
- RFC 8705: OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access TokensIETF
- SPIFFE overviewSPIFFE (Cloud Native Computing Foundation)
- SP 800-207: Zero Trust ArchitectureNIST