حماية الموارد من هجمات الويب باستخدام ميزة "جلب البيانات الوصفية"

منع تسرُّب معلومات CSRF وXSSI والمعلومات المتعددة المصادر.

لماذا يجب الاهتمام بعزل موارد الويب؟

العديد من تطبيقات الويب تكون عرضة للهجمات من مصادر متعددة، مثل تزوير الطلبات من مواقع إلكترونية متعددة (CSRF) أو تضمين النصوص البرمجية على مواقع إلكترونية متعددة (XSSI) أو هجمات التوقيت أو تسرُّب المعلومات من مصادر متعددة أو هجمات القنوات الجانبية للتنفيذ المبني على توقُّع (Spectre).

تتيح لك عناوين طلبات جلب البيانات الوصفية نشر آلية قوية لحماية البيانات، وهي "سياسة عزل الموارد"، لحماية تطبيقك من هذه الهجمات الشائعة من عدة مصادر.

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

توافُق المتصفح

إنّ عناوين طلبات استرجاع البيانات الوصفية متوافقة مع جميع محرّكات المتصفّحات الحديثة.

دعم المتصفح

  • Chrome: 76.
  • الحافة: 79.
  • Firefox: 90
  • Safari: الإصدار 16.4.

المصدر

الخلفية

يمكن حدوث العديد من الهجمات التي تتم على مواقع إلكترونية مختلفة لأنّ شبكة الإنترنت مفتوحة تلقائيًا وأنّ خادم التطبيقات لا يمكنه حماية نفسه بسهولة من الاتصالات الناشئة عن تطبيقات خارجية. والهجمات المتعددة المصادر النموذجية هي تزوير الطلبات من مواقع إلكترونية متعددة (CSRF) حيث يستدرج المهاجم مستخدمًا إلى موقع إلكتروني يتحكم فيه، ثم يرسل نموذجًا إلى الخادم الذي سجّل المستخدم الدخول إليه. وبما أنّ الخادم لا يمكنه معرفة ما إذا نشأ الطلب من نطاق آخر (من مواقع إلكترونية متعددة) وكان المتصفّح يرفق ملفات تعريف الارتباط تلقائيًا بالطلبات من عدة مواقع إلكترونية، سينفِّذ الخادم الإجراء الذي طلبه المهاجم بالنيابة عن المستخدم.

وتكون الهجمات الأخرى على مواقع إلكترونية مختلفة، مثل تضمين نصوص برمجية من مواقع إلكترونية متعددة (XSSI) أو تسرُّب المعلومات من مصادر متعددة، مماثلة في طبيعتها لـ CSRF، وتعتمد على تحميل الموارد من تطبيق الضحية في مستند يتحكّم فيه المهاجم وتسرّب المعلومات حول التطبيقات المعرّضة للهجوم. ولأنّ التطبيقات لا يمكنها بسهولة التمييز بين الطلبات الموثوق بها وتلك غير الموثوق بها، لا يمكنها تجاهل الزيارات الضارّة على جميع المواقع الإلكترونية.

لمحة عن البيانات الوصفية المتعلّقة بعملية الجلب

عناوين طلبات استرجاع البيانات الوصفية هي ميزة أمان جديدة للنظام الأساسي للويب مصمَّمة لمساعدة الخوادم في الدفاع عن نفسها ضد الهجمات متعددة المصادر. من خلال توفير معلومات عن سياق طلب HTTP في مجموعة من عناوين Sec-Fetch-*، يتم السماح لخادم الاستجابة بتطبيق سياسات الأمان قبل معالجة الطلب. ويتيح ذلك للمطوّرين تحديد ما إذا كان سيتم قبول الطلب أو رفضه استنادًا إلى طريقة تقديمه والسياق الذي سيتم استخدامه فيه، ما يتيح إمكانية الردّ على الطلبات المشروعة فقط التي يتم تقديمها من خلال تطبيقاتهم الخاصة.

المصدر نفسه
وسيستمر عمل الطلبات الواردة من المواقع الإلكترونية التي يعرضها خادمك الخاص (المصدر نفسه). يؤدّي طلب استرجاع من https://site.example للمورد https://site.example/foo.json في JavaScript إلى إرسال المتصفِّح لعنوان طلب HTTP وهو "Sec Fetch-Site: same-origin".
على جميع المواقع
يمكن أن يرفض الخادم الطلبات الضارة من مواقع إلكترونية متعددة بسبب السياق الإضافي في طلب HTTP المقدَّم من عناوين Sec-Fetch-*. صورة على https://evil.example تم ضبط السمة src لعنصر img على "https://site.example/foo.json" تتسبب في إرسال المتصفح لعنوان طلب HTTP "Sec-Fetch-Site: cross-site".

Sec-Fetch-Site

دعم المتصفح

  • Chrome: 76.
  • الحافة: 79.
  • Firefox: 90
  • Safari: الإصدار 16.4.

المصدر

يخبر Sec-Fetch-Site الخادم باسم الموقع الإلكتروني الذي أرسل الطلب. ويضبط المتصفّح هذه القيمة على إحدى القيم التالية:

  • same-origin، إذا تم تقديم الطلب من خلال تطبيقك (مثل site.example)
  • same-site، إذا تم تقديم الطلب من خلال نطاق فرعي لموقعك الإلكتروني (مثل bar.site.example)
  • none، إذا كان الطلب قد نتج بشكل صريح عن تفاعل أحد المستخدمين مع وكيل المستخدم (مثل النقر على إشارة مرجعية)
  • cross-site، إذا تم إرسال الطلب من خلال موقع إلكتروني آخر (مثل evil.example)

Sec-Fetch-Mode

دعم المتصفح

  • Chrome: 76.
  • الحافة: 79.
  • Firefox: 90
  • Safari: الإصدار 16.4.

المصدر

تشير السمة Sec-Fetch-Mode إلى وضع الطلب. ويتوافق هذا تقريبًا مع نوع الطلب، ويتيح لك التفريق بين عمليات تحميل الموارد وطلبات التنقل. على سبيل المثال، تشير وجهة navigate إلى طلب التنقّل على المستوى الأعلى، بينما تشير no-cors إلى طلبات الموارد، مثل تحميل صورة.

Sec-Fetch-Dest

دعم المتصفح

  • Chrome: 80.
  • الحافة: 80.
  • Firefox: 90
  • Safari: الإصدار 16.4.

المصدر

تعرض السمة Sec-Fetch-Dest وجهة الطلب (على سبيل المثال، إذا تسبّبت علامة script أو img في طلب المتصفّح لمورد).

كيفية استخدام البيانات الوصفية لاسترجاع البيانات للحماية من الهجمات ذات المصادر المختلفة

المعلومات الإضافية التي تقدمها عناوين الطلبات هذه بسيطة للغاية، ولكن السياق الإضافي يتيح لك إنشاء منطق أمان قوي من جانب الخادم، ويشار إليه أيضًا باسم "سياسة عزل الموارد"، باستخدام بضعة أسطر من الرموز.

تنفيذ سياسة عزل الموارد

تمنع سياسة عزل الموارد طلب مواردك من خلال مواقع إلكترونية خارجية. يحدّ حظر مثل هذه الزيارات من الثغرات الأمنية الشائعة على الويب في جميع المواقع الإلكترونية، مثل 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/foo.json من site.example).
  • أن تكون واردة من نطاقاتك الفرعية.
  • تحدث صراحةً عن تفاعل المستخدم مع وكيل المستخدم (مثل التنقل المباشر أو النقر على إشارة مرجعية، وما إلى ذلك).
if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
  return True  # Allow this request

الخطوة 3: السماح بالتنقّل البسيط على المستوى الأعلى وإضافة إطارات iframe

لضمان إمكانية ربط موقعك الإلكتروني من مواقع إلكترونية أخرى، عليك السماح بالتنقل البسيط في المستوى الأعلى (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

نشر سياسة عزل الموارد

  1. ثبِّت وحدة مثل مقتطف الرمز أعلاه لتسجيل سلوك موقعك الإلكتروني ومراقبته، والتأكّد من أنّ القيود لا تؤثر في أي زيارات مشروعة.
  2. أصلِح الانتهاكات المحتملة من خلال استثناء نقاط النهاية المشروعة المتعددة المصادر.
  3. نفِّذ السياسة عن طريق حذف الطلبات غير الممتثلة للسياسة.

تحديد انتهاكات السياسة وإصلاحها

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

بناءً على خبرتنا في طرح سياسة عزل موارد البيانات الوصفية في Google، تكون معظم التطبيقات متوافقة تلقائيًا مع هذه السياسة ونادرًا ما تتطلب نقاط نهاية معفاة للسماح بالزيارات من مواقع إلكترونية متعددة.

فرض سياسة عزل الموارد

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

محتوى إضافي للقراءة