منع تسرُّب المعلومات عبر هجمات CSRF وXSSI وهجمات المصادر المختلفة
لماذا يجب الانتباه إلى عزل موارد الويب؟
تتعرّض العديد من تطبيقات الويب لهجمات من مصادر مختلفة، مثل تزوير الطلبات من مواقع إلكترونية مختلفة (CSRF) وإدراج البرامج النصية على مواقع إلكترونية مختلفة (XSSI) وهجمات التوقيت وتسرُّب المعلومات من مصادر مختلفة أو هجمات قناة التنفيذ التوقّعي (Spectre).
تسمح لك رؤوس طلبات Fetch Metadata بنشر آلية دفاعية قوية ومفصّلة، وهي سياسة عزل الموارد، لحماية تطبيقك من هذه الهجمات الشائعة المشتركة المصدر.
من الشائع أن يتم تحميل الموارد التي يعرضها تطبيق ويب معيّن من خلال التطبيق نفسه فقط، وليس من خلال مواقع إلكترونية أخرى. في هذه الحالات، لا يتطلّب نشر سياسة عزل الموارد استنادًا إلى رؤوس طلبات Fetch Metadata سوى مجهود بسيط، وفي الوقت نفسه يحمي التطبيق من الهجمات على مستوى المواقع الإلكترونية.
توافُق المتصفح
تتوفّر عناوين طلبات Fetch Metadata في جميع محرّكات المتصفّحات الحديثة.
الخلفية
من الممكن أن تحدث العديد من الهجمات على مستوى المواقع الإلكترونية لأنّ الويب مفتوح تلقائيًا ولا يمكن لخادم التطبيقات حماية نفسه بسهولة من الاتصالات الواردة من تطبيقات خارجية. ومن الأمثلة الشائعة على هجمات المصادر المختلفة هو التزوير عبر المواقع الإلكترونية (CSRF)، حيث يجذب المهاجم مستخدمًا إلى موقع إلكتروني يتحكّم فيه، ثم يُرسل نموذجًا إلى الخادم الذي سجّل المستخدم الدخول إليه. بما أنّ الخادم لا يمكنه معرفة ما إذا كان الطلب مصدره نطاقًا آخر (خارج الموقع) ويُرفِق المتصفح تلقائيًا ملفات تعريف الارتباط بطلبات المواقع الإلكترونية الأخرى، سينفِّذ الخادم الإجراء الذي طلبه المهاجم نيابةً عن المستخدم.
تشبه الهجمات الأخرى على مستوى الموقع الإلكتروني، مثل تضمين النصوص البرمجية على مستوى الموقع الإلكتروني (XSSI) أو تسرُّب المعلومات من مصادر متعددة، هجوم CSRF من حيث الطبيعة، وتعتمد على تحميل الموارد من تطبيق ضحية في مستند يتحكّم فيه المهاجم وتسرُّب معلومات عن التطبيقات الضحية. وبما أنّ التطبيقات لا يمكنها بسهولة التمييز بين الطلبات الموثوق بها والطلبات غير الموثوق بها، لا يمكنها تجاهل الزيارات الضارة على مستوى المواقع الإلكترونية.
تقديم ميزة "جلب البيانات الوصفية"
عناوين طلب Fetch Metadata هي ميزة جديدة لأمان منصات الويب مصمّمة لمساعدة الخوادم في الدفاع عن نفسها ضد الهجمات من مصادر متعددة. من خلال تقديم معلومات عن سياق طلب HTTP في مجموعة من رؤوس Sec-Fetch-*
، تسمح هذه الرؤوس للخادم المُجيب بتطبيق سياسات الأمان قبل معالجة الطلب. يتيح ذلك للمطوّرين تحديد ما إذا كانوا يريدون قبول طلب معيّن أو رفضه استنادًا إلى طريقة تقديمه والسياق الذي سيتم استخدامه فيه، ما يتيح الردّ على الطلبات المشروعة فقط التي يقدّمها تطبيقهم.
Sec-Fetch-Site
يُخبر Sec-Fetch-Site
الخادم بموقع الويب الذي أرسل الطلب. يضبط المتصفّح هذه القيمة على إحدى القيم التالية:
same-origin
، إذا تم تقديم الطلب من خلال تطبيقك الخاص (مثلsite.example
)same-site
، إذا تم تقديم الطلب من نطاق فرعي لموقعك الإلكتروني (مثلbar.site.example
)none
، إذا كان الطلب ناتجًا بشكل صريح عن تفاعل أحد المستخدمين مع وكيل المستخدم (مثل النقر على إشارة مرجعية)cross-site
، إذا تم إرسال الطلب من موقع إلكتروني آخر (مثلevil.example
)
Sec-Fetch-Mode
يشير Sec-Fetch-Mode
إلى وضع الطلب. ويتوافق ذلك تقريبًا مع نوع الطلب ويسمح لك بالتمييز بين عمليات تحميل الموارد وطلبات التنقّل. على سبيل المثال، تشير الوجهة navigate
إلى طلب تنقّل على المستوى الأعلى، في حين تشير الوجهة no-cors
إلى طلبات الموارد، مثل تحميل صورة.
Sec-Fetch-Dest
تعرِض Sec-Fetch-Dest
وجهة الطلب (على سبيل المثال، إذا تسبّبت علامة script
أو img
في طلب المتصفّح لمصدر).
كيفية استخدام Fetch Metadata للحماية من الهجمات من مصادر متعددة
إنّ المعلومات الإضافية التي تقدّمها رؤوس الطلبات هذه بسيطة جدًا، ولكنّ السياق الإضافي يسمح لك بإنشاء منطق أمان قوي من جهة الخادم، ويُشار إليه أيضًا باسم "سياسة عزل الموارد"، وذلك باستخدام بضعة أسطر من الرموز البرمجية فقط.
تنفيذ سياسة عزل الموارد
تمنع سياسة عزل الموارد المواقع الإلكترونية الخارجية من طلب مواردك. ويؤدي حظر هذه الزيارات إلى تخفيف الثغرات الأمنية الشائعة على الويب على مستوى المواقع الإلكترونية المختلفة، مثل هجمات CSRF وXSSI وهجمات التوقيت وتسرُّب المعلومات من مصادر مختلفة. يمكن تفعيل هذه السياسة لجميع نقاط النهاية في تطبيقك، وستسمح بجميع طلبات الموارد الواردة من تطبيقك بالإضافة إلى عمليات التنقّل المباشرة (عبر طلب HTTP GET
). يمكن إيقاف هذا المنطق في نقاط النهاية التي من المفترض أن يتم تحميلها في سياق على مستوى المواقع الإلكترونية (مثل نقاط النهاية التي يتم تحميلها باستخدام CORS).
الخطوة 1: السماح بالطلبات الواردة من المتصفّحات التي لا تُرسِل طلبات الحصول على البيانات الوصفية
بما أنّ بعض المتصفّحات لا تتيح استخدام ميزة "جلب البيانات الوصفية"، عليك السماح بالطلبات التي لا تضبط رؤوس Sec-Fetch-*
من خلال التحقّق من توفّر sec-fetch-site
.
if not req['sec-fetch-site']:
return True # Allow this request
الخطوة 2: السماح بالطلبات التي تبدأ من الموقع الإلكتروني نفسه أو المتصفّح
سيتم السماح بأي طلبات لا تصدر عن سياق من مصدر خارجي (مثل evil.example
). وعلى وجه التحديد، تشمل هذه الطلبات ما يلي:
- أن يكون مصدرها من تطبيقك الخاص (مثل طلب من المصدر نفسه يسمح فيه
site.example
دائمًا بطلباتsite.example/foo.json
) - أن تأتي من نطاقاتك الفرعية
- أن تكون ناتجة صراحةً عن تفاعل المستخدم مع وكيل المستخدم (مثلاً، التنقل المباشر أو النقر على إشارة مرجعية وما إلى ذلك)
if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
return True # Allow this request
الخطوة 3: السماح بالتنقّل البسيط على مستوى أعلى واستخدام تقنية iframing
لضمان استمرار إمكانية ربط موقعك الإلكتروني من مواقع إلكترونية أخرى، عليك السماح بالتنقّل البسيط (HTTP GET
) على المستوى الأعلى.
if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET'
# <object> and <embed> send navigation requests, which we disallow.
and req['sec-fetch-dest'] not in ('object', 'embed'):
return True # Allow this request
الخطوة 4: إيقاف نقاط النهاية المخصّصة لعرض الزيارات على مستوى الموقع الإلكتروني (اختياري)
في بعض الحالات، قد يقدّم تطبيقك موارد يُفترض تحميلها على مستوى الموقع الإلكتروني. يجب إعفاء هذه الموارد على أساس كل مسار أو نقطة نهاية. في ما يلي أمثلة على نقاط النهاية هذه:
- نقاط النهاية التي يُفترض الوصول إليها من مصادر متعددة: إذا كان تطبيقك يعرض نقاط نهاية مفعَّلة
CORS
، عليك إيقاف عزل الموارد لها بشكل صريح لضمان استمرار إمكانية إرسال طلبات من مواقع إلكترونية متعددة إلى نقاط النهاية هذه. - الموارد المتاحة للجميع (مثل الصور والأنماط وما إلى ذلك): يمكن أيضًا استثناء أيّ مصادر عامة وغير مُعتمَدة يجب أن تكون قابلة للتحميل من مصادر متعددة من مواقع إلكترونية أخرى.
if req.path in ('/my_CORS_endpoint', '/favicon.png'):
return True
الخطوة 5: رفض جميع الطلبات الأخرى التي تتجاوز نطاق الموقع الإلكتروني وليست لأغراض التنقّل
سترفض سياسة عزل الموارد هذه أي طلب آخر من مواقع إلكترونية أخرى، وبالتالي ستحمي تطبيقك من الهجمات الشائعة على عدة مواقع إلكترونية.
مثال: يوضّح الرمز البرمجي التالي تنفيذًا كاملاً لسياسة عزل الموارد القوية على الخادم أو كوسيط لرفض طلبات الموارد التي يُحتمل أن تكون ضارة على مستوى المواقع الإلكترونية، مع السماح بطلبات التنقّل البسيطة:
# Reject cross-origin requests to protect from CSRF, XSSI, and other bugs
def allow_request(req):
# Allow requests from browsers which don't send Fetch Metadata
if not req['sec-fetch-site']:
return True
# Allow same-site and browser-initiated requests
if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
return True
# Allow simple top-level navigations except <object> and <embed>
if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET'
and req['sec-fetch-dest'] not in ('object', 'embed'):
return True
# [OPTIONAL] Exempt paths/endpoints meant to be served cross-origin.
if req.path in ('/my_CORS_endpoint', '/favicon.png'):
return True
# Reject all other requests that are cross-site and not navigational
return False
نشر سياسة عزل الموارد
- ثبِّت وحدة مثل مقتطف الرمز أعلاه لتسجيل سلوك موقعك الإلكتروني ومراقبته والتأكّد من أنّ القيود لا تؤثّر في أي زيارات مشروعة.
- يمكنك إصلاح الانتهاكات المحتمَلة من خلال إعفاء نقاط النهاية الصالحة التي تتعامل مع مصادر متعددة.
- فرض السياسة من خلال رفض الطلبات غير المتوافقة
تحديد انتهاكات السياسة وإصلاحها
ننصحك باختبار سياستك بطريقة خالية من الآثار الجانبية من خلال تفعيلها أولاً في وضع إعداد التقارير في الرمز البرمجي من جهة الخادم. كخيار بديل، يمكنك تنفيذ هذا المنطق في الوسيط أو في خادم وكيل عكسي يسجّل أي انتهاكات قد تنتج عن سياستك عند تطبيقها على عدد الزيارات الفعلية.
استنادًا إلى خبرتنا في طرح سياسة عزل موارد جلب البيانات الوصفية في Google، تكون معظم التطبيقات متوافقة تلقائيًا مع هذه السياسة ونادراً ما تتطلّب إعفاء نقاط النهاية للسماح بالزيارات على مستوى المواقع الإلكترونية.
فرض سياسة عزل الموارد
بعد التأكّد من أنّ سياستك لا تؤثّر في الزيارات المشروعة في قناة الإصدار، ستكون مستعدًا لفرض القيود، ما يضمن عدم تمكّن المواقع الإلكترونية الأخرى من طلب مواردك وحماية المستخدمين من الهجمات على مستوى المواقع الإلكترونية.
مراجع إضافية
- مواصفات رؤوس طلبات جلب البيانات الوصفية من W3C
- Fetch Metadata Playground
- محادثة Google I/O: تأمين تطبيقات الويب باستخدام ميزات المنصة الحديثة (العروض التقديمية)