سياسة أمان المحتوى

يكون نموذج أمان الويب مستندًا إلى سياسة المصدر نفسه. الرمز من https://mybank.com يجب أن يقتصر على الوصول إلى بيانات https://mybank.com، وبالتأكيد لا يُسمح بالوصول إلى https://evil.example.com. ويتم الحفاظ على عزل كل مصدر عن بقية المواقع الإلكترونية، ما يمنح المطوّرين وضع حماية آمن للإنشاء واللعب. من الناحية النظرية، هذا رائع تمامًا. من الناحية العملية، وجد المهاجمون طرقًا ذكية لإسقاط النظام.

هجمات البرمجة النصية على المواقع الإلكترونية (XSS)، على سبيل المثال، تتجاوز سياسة المصدر نفسها من خلال خداع الموقع الإلكتروني لإرسال رمز ضار مع المحتوى المقصود. وتعد هذه مشكلة كبيرة، حيث تثق المتصفحات في جميع الرموز التي تظهر على الصفحة باعتبارها جزءًا من أصل أمان تلك الصفحة. وورقة المعلومات المرجعية لـ XSS هي جزء قديم ولكنه تمثيلي يستعرض العديد من الطرق التي قد يستخدمها المهاجم لاختراق هذه الثقة عن طريق إدخال رمز ضار. وإذا نجح أحد المهاجمين في إدخال أي رمز على الإطلاق، فسينتهي الأمر إلى حد كبير: فقد تكون بيانات جلسة المستخدم عرضة للاختراق ويتم استخراج المعلومات التي يجب الحفاظ على سريتها إلى The Bad Guys. كما أننا نرغب في منع ذلك إن أمكن.

تلقي هذه النظرة العامة الضوء على الدفاع الذي يمكنه الحد بشكل كبير من خطر وتأثير هجمات XSS في المتصفحات الحديثة: سياسة أمان المحتوى (CSP).

الملخّص

  • استخدِم القوائم المسموح بها لإعلام العميل بالمنتجات المسموح بها وغير المسموح بها.
  • تعرَّف على الأوامر المتاحة.
  • التعرف على الكلمات الرئيسية التي تستخدمها.
  • يُعدّ الرمز المضمَّن والرمز eval() ضارًا.
  • إبلاغ خادمك عن انتهاكات السياسة قبل فرضها.

القوائم المسموح بها للمصادر

المشكلة التي تستغلها هجمات XSS هي عدم قدرة المتصفح على التمييز بين النص البرمجي الذي يُعد جزءًا من التطبيق والنص البرمجي الذي تم إدخاله عن طريق الخطأ بواسطة جهة خارجية. على سبيل المثال، يعمل زر Google +1 الموجود في أسفل هذه الصفحة على تحميل وتنفيذ الرموز من https://apis.google.com/js/plusone.js في سياق مصدر هذه الصفحة. نحن نثق في هذا الرمز، ولكننا لا نتوقع أن يكتشف المتصفح بنفسه أنّ الرمز الوارد من apis.google.com رائع، على عكس الرمز من apis.evil.example.com على الأرجح. ويعمل المتصفح على تنزيل أي رمز برمجي تطلبه الصفحة وتنفيذه بسهولة، بغض النظر عن مصدره.

بدلاً من الوثوق بشكل عشوائي بكل ما يقدّمه الخادم، تحدِّد سياسة CSP عنوان HTTP يتضمّن Content-Security-Policy، ما يسمح لك بإنشاء قائمة مسموح بها من مصادر المحتوى الموثوق به، ويوجّه المتصفِّح إلى تنفيذ الموارد فقط أو عرضها من تلك المصادر. حتى إذا تمكن مهاجم من العثور على ثقب يمكن من خلاله إدخال نص برمجي، لن يتطابق النص البرمجي مع القائمة المسموح بها، وبالتالي لن يتم تنفيذه.

بما أنّنا نثق في apis.google.com لتقديم رمز صالح، ولأنّنا نثق بأنفسنا، سنعرف أيضًا السياسة التي لا تسمح بتنفيذ النص البرمجي إلّا إذا جاءت من أحد هذين المصدرَين:

Content-Security-Policy: script-src 'self' https://apis.google.com

أمر بسيط للغاية، أليس كذلك؟ إنّ script-src، كما خمنت على الأرجح، هو توجيه يتحكّم في مجموعة من الامتيازات المتعلّقة بالنص البرمجي لصفحة معيّنة. لقد حدّدنا 'self' كمصدر صالح للنص البرمجي، وhttps://apis.google.com كمصدر آخر. ينزّل المتصفّح JavaScript وينفّذها بشكل متكرر من apis.google.com عبر HTTPS، وكذلك من أصل الصفحة الحالية.

خطأ في وحدة التحكّم: تم رفض تحميل النص البرمجي "http://evil.example.com/evil.js" لأنه ينتهك التوجيه التالي لسياسة أمان المحتوى: script-src 'self' https://apis.google.com

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

تنطبق السياسة على مجموعة متنوعة من الموارد

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

لنتصفح بقية توجيهات الموارد بسرعة. تمثل القائمة أدناه حالة الأوامر اعتبارًا من المستوى 2. تم نشر مواصفات المستوى الثالث، ولكن لم يتم تنفيذها إلى حد كبير في المتصفحات الرئيسية.

  • يحظر base-uri عناوين URL التي يمكن أن تظهر في عنصر <base> لإحدى الصفحات.
  • يسرد child-src عناوين URL للعاملين ومحتوى الإطارات المضمَّنة. على سبيل المثال: تسمح السمة child-src https://youtube.com بتضمين الفيديوهات من YouTube ولكن ليس من مصادر أخرى.
  • تفرض connect-src قيودًا على المصادر التي يمكنك الاتصال بها (من خلال XHR وWebSockets وEventSource).
  • تحدّد السمة font-src المصادر التي يمكنها عرض خطوط الويب. يمكن تفعيل خطوط الويب من Google عبر font-src https://themes.googleusercontent.com.
  • يسرد form-action نقاط النهاية الصالحة للإرسال من علامات <form>.
  • تحدّد السمة frame-ancestors المصادر التي يمكنها تضمين الصفحة الحالية. ينطبق هذا التوجيه على علامات <frame> و<iframe> و<embed> و<applet>. لا يمكن استخدام هذا التوجيه في علامات <meta> ولا ينطبق إلا على الموارد التي ليست بتنسيق HTML.
  • تم إيقاف frame-src نهائيًا في المستوى 2، ولكن تمت استعادته في المستوى 3. إذا لم تكن موجودة، ستظل تعود إلى child-src كما في السابق.
  • تحدِّد السمة img-src المصادر التي يمكن تحميل الصور منها.
  • تفرض media-src قيودًا على المصادر المسموح لها بإرسال الفيديو والصوت.
  • يسمح object-src بالتحكم في Flash والمكوّنات الإضافية الأخرى.
  • يفرض plugin-types قيودًا على أنواع المكوّنات الإضافية التي قد تستدعي الصفحة.
  • تحدّد report-uri عنوان URL الذي سيرسل إليه المتصفّح تقارير عند انتهاك سياسة أمان المحتوى. ولا يمكن استخدام هذا التوجيه في علامات <meta>.
  • الأداة style-src هي نظير script-src لأوراق الأنماط.
  • توجِّه upgrade-insecure-requests برامج وكيل المستخدم إلى إعادة كتابة مخططات عناوين URL، مع تغيير HTTP إلى HTTPS. هذا التوجيه مخصص لمواقع الويب التي تضم أعدادًا كبيرة من عناوين URL القديمة التي تحتاج إلى إعادة كتابتها.
  • worker-src هو توجيه من المستوى 3 في سياسة أمان المحتوى (CSP) يحدّ من عناوين URL التي يمكن تحميلها كعامل تشغيل أو عامل مشترك أو مشغّل خدمات. اعتبارًا من تموز (يوليو) 2017، أصبح لهذا التوجيه عمليات تنفيذ محدودة.

بشكل افتراضي، تكون التوجيهات مفتوحة على نطاق واسع. إذا لم تحدّد سياسة محدّدة لتوجيه معيّن، مثل font-src، يعمل هذا التوجيه تلقائيًا كما لو أنّك حدّدت * كمصدر صالح (على سبيل المثال، يمكنك تحميل الخطوط من أي مكان وبدون قيود).

يمكنك إلغاء هذا السلوك التلقائي من خلال تحديد توجيه default-src. يحدد هذا التوجيه الإعدادات الافتراضية لمعظم التوجيهات التي تتركها غير محددة. وينطبق ذلك بشكل عام على أي توجيه ينتهي بـ -src. في حال ضبط default-src على https://example.com، وتعذّر عليك تحديد التوجيه font-src، يمكنك تحميل الخطوط من https://example.com وليس أي مواقع أخرى. لقد حدّدنا فقط script-src في أمثلتنا السابقة، ما يعني أنّه يمكن تحميل الصور والخطوط وما إلى ذلك من أي مصدر.

لا تستخدِم التوجيهات التالية default-src كبديل. تذكر أن عدم تعيينها يشبه السماح بأي شيء.

  • base-uri
  • form-action
  • frame-ancestors
  • plugin-types
  • report-uri
  • sandbox

يمكنك استخدام أكبر عدد أو قليل من هذه التوجيهات حسبما يكون مناسبًا لتطبيقك الخاص، وما عليك سوى إدراج كل منها في عنوان HTTP، وفصل التوجيهات بفواصل منقوطة. تأكَّد من إدراج جميع الموارد المطلوبة من نوع محدّد في توجيه واحد. إذا كتبت شيئًا مثل script-src https://host1.com; script-src https://host2.com، سيتم ببساطة تجاهل التوجيه الثاني. قد يحدد شيء مثل التالي كلا المصدرين على النحو الصحيح:

script-src https://host1.com https://host2.com

على سبيل المثال، إذا كان لديك تطبيق يُحمِّل جميع موارده من شبكة توصيل المحتوى (على سبيل المثال، https://cdn.example.net)، وكنت تعرف أنّك لا تحتاج إلى أيّ محتوى بإطار أو مكوّنات إضافية، قد تبدو سياستك على النحو التالي:

Content-Security-Policy: default-src https://cdn.example.net; child-src 'none'; object-src 'none'

تفاصيل التنفيذ

ستظهر لك العناوين X-WebKit-CSP وX-Content-Security-Policy في برامج تعليمية مختلفة على الويب. من الآن فصاعدًا، يجب عليك تجاهل هذه الرؤوس ذات البادئات. تتوافق المتصفّحات الحديثة (باستثناء IE) مع عنوان Content-Security-Policy غير المسبَق. هذا هو العنوان الذي يجب أن تستخدمه.

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

تتميز قائمة المصادر في كل توجيه بالمرونة. يمكنك تحديد المصادر حسب المخطط (data: أو https:) أو النطاق في الخصوصية بدءًا من اسم المضيف فقط (example.com، الذي يتطابق مع أي مصدر على ذلك المضيف: أي مخطط أو أيّ منفذ) إلى معرّف موارد منتظم (URI) مؤهل بالكامل (https://example.com:443، والذي يتطابق فقط مع HTTPS وexample.com، والذي يتطابق فقط مع المنفذ 443). يتم قبول أحرف البدل فقط كمخطط أو منفذ أو في أقصى موضع من يسار اسم المضيف: سيتطابق *://*.example.com:* مع جميع النطاقات الفرعية لـ example.com (ولكن ليس example.com نفسه)، باستخدام أي مخطط، على أي منفذ.

تقبل قائمة المصدر أيضًا أربع كلمات رئيسية:

  • قد لا تتطابق قيمة 'none' مع أي نتائج.
  • يتطابق العنصر 'self' مع المصدر الحالي، ولكن لا يتطابق مع نطاقاته الفرعية.
  • يسمح 'unsafe-inline' بتضمين JavaScript وCSS. (سنتطرق إليه بمزيد من التفصيل بعد قليل.)
  • يسمح 'unsafe-eval' بآليات تحويل النص إلى JavaScript مثل eval. (سنصل إلى هذا أيضًا.)

تتطلب هذه الكلمات الرئيسية علامات اقتباس مفردة. على سبيل المثال، يسمح script-src 'self' (مع وضع علامات اقتباس) بتنفيذ JavaScript من المضيف الحالي، بينما يسمح script-src self (بدون علامات اقتباس) بتنفيذ JavaScript من خادم يُسمى "self" (وليس من المضيف الحالي)، وهذا على الأرجح ليس ما تقصده.

وضع الحماية

هناك توجيه آخر يستحق الحديث عنه: sandbox. وتختلف قليلاً عن الإجراءات الأخرى التي راجعناها، لأنّها تفرض قيودًا على الإجراءات التي يمكن أن تتخذها الصفحة بدلاً من الموارد التي يمكن أن تحمِّلها الصفحة. وفي حال توفّر التوجيه sandbox، يتم التعامل مع الصفحة كما لو تم تحميلها داخل <iframe> مع السمة sandbox. وقد يكون لذلك مجموعة كبيرة من التأثيرات على الصفحة، منها فرض إنشاء الصفحة على مصدر فريد ومنع إرسال النماذج وغير ذلك. إنها خارج نطاق هذه المقالة قليلاً، ولكن يمكنك العثور على التفاصيل الكاملة حول السمات الصالحة لوضع الحماية في قسم "وضع الحماية" في مواصفات HTML5.

العلامة الوصفية

آلية التسليم المفضلة لمقدّمي خدمة العملاء (CSP) هي عنوان HTTP. ومع ذلك، قد يكون من المفيد ضبط سياسة على إحدى الصفحات من خلال الترميز مباشرةً. يمكنك إجراء ذلك باستخدام علامة <meta> مع السمة http-equiv:

<meta
  http-equiv="Content-Security-Policy"
  content="default-src https://cdn.example.net; child-src 'none'; object-src 'none'"
/>

لا يمكن استخدام هذا الإعداد للحساب frame-ancestors أو report-uri أو sandbox.

يُعد الرمز البرمجي المضمّن ضارًا.

من الواضح أنّ سياسة CSP تستند إلى مصادر القائمة المسموح بها، لأنّها طريقة واضحة لتوجيه المتصفّح إلى التعامل مع مجموعات معيّنة من الموارد على أنّها مقبولة ورفض الباقي. مع ذلك، فإنّ القوائم المسموح بها المستندة إلى المصدر لا تحل التهديد الأكبر الذي تشكّله هجمات XSS، وهو "إدخال النصوص البرمجية المضمّنة". إذا تمكّن أحد المهاجمين من إدخال علامة نص برمجي تحتوي مباشرةً على بعض الحمولة الضارة (<script>sendMyDataToEvilDotCom();</script>)، فلن يكون لدى المتصفح أي آلية لتمييزه عن علامة نص برمجي مضمّنة مشروعة. تحل سياسة CSP هذه المشكلة من خلال حظر النص البرمجي المضمّن تمامًا: إنها الطريقة الوحيدة للتأكد.

لا يشمل هذا الحظر النصوص البرمجية المضمّنة مباشرةً في علامات script فحسب، بل يشمل أيضًا معالِجات الأحداث المضمّنة وعناوين URL التي تتضمّن javascript:. عليك نقل محتوى علامات script إلى ملف خارجي واستبدال عناوين URL التي تتضمّن javascript: و<a ... onclick="[JAVASCRIPT]"> باستدعاءات addEventListener() المناسبة. على سبيل المثال، يمكنك إعادة كتابة ما يلي من:

<script>
  function doAmazingThings() {
    alert('YOU AM AMAZING!');
  }
</script>
<button onclick="doAmazingThings();">Am I amazing?</button>

إلى شيء أكثر مثل:

<!-- amazing.html -->
<script src="amazing.js"></script>
<button id="amazing">Am I amazing?</button>

<div style="clear:both;"></div>
// amazing.js
function doAmazingThings() {
  alert('YOU AM AMAZING!');
}
document.addEventListener('DOMContentLoaded', function () {
  document.getElementById('amazing').addEventListener('click', doAmazingThings);
});

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

يتم التعامل مع النمط المضمَّن بالطريقة نفسها: يجب دمج كلّ من السمة style وعلامات style في أوراق أنماط خارجية للحماية من مجموعة متنوعة من طرق استخراج البيانات المدهشة بشكل مدهش التي تتيحها خدمة CSS.

إذا كان يجب أن يتوفّر لديك نص ونمط مضمّنَين، يمكنك تفعيله من خلال إضافة 'unsafe-inline' كمصدر مسموح به في توجيه script-src أو style-src. يمكنك أيضًا استخدام nonce أو تجزئة (انظر أدناه)، ولكن لا يجب عليك ذلك. إنّ حظر النص البرمجي المضمّن هو أكبر مكاسب أمنية تقدّمها سياسة CSP، كما يؤدي حظر النمط المضمّن إلى تقوية تطبيقك. هناك القليل من الجهد مقدمًا لضمان سير الأمور بشكل صحيح بعد نقل جميع التعليمات البرمجية خارج الخط، ولكن هذه هي المقايضة التي تستحق القيام بها.

إذا كنت مضطرًا لاستخدام هذه الميزة

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

لاستخدام nonce، امنح علامة النص البرمجي سمة nonce. ويجب أن تتطابق قيمتها مع قيمة واحدة في قائمة المصادر الموثوقة. مثلاً:

<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
  // Some inline code I can't remove yet, but need to asap.
</script>

والآن، أضِف الجزء الخاص من التوجيه script-src إلى الكلمة الرئيسية nonce-.

Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'

وتذكَّر أنّه يجب إعادة إنشاء الأرقام الخاصة بكل طلب صفحة ويجب ألّا تكون قابلة للتخمين.

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

<script>
  alert('Hello, world.');
</script>

ستحتوي سياستك على ما يلي:

Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='

في ما يلي بعض النقاط. تحدد البادئة sha*- الخوارزمية التي تنشئ التجزئة. في المثال أعلاه، يتم استخدام sha256-. تتوافق سياسة CSP أيضًا مع sha384- وsha512-. عند إنشاء التجزئة، لا تضمِّن علامات <script>. كما أن الأحرف الكبيرة والمسافات البيضاء، بما في ذلك المسافات البيضاء البادئة أو اللاحقة.

سيقودك بحث Google حول إنشاء تجزئات SHA إلى حلول بأي عدد من اللغات. باستخدام Chrome 40 أو إصدار أحدث، يمكنك فتح "أدوات مطوري البرامج" ثم إعادة تحميل صفحتك. ستحتوي علامة التبويب "وحدة التحكم" على رسائل خطأ بتجزئة sha256 الصحيحة لكل من النصوص البرمجية المضمّنة.

Eval أيضًا

حتى عندما لا يتمكن المهاجم من إدخال النص البرمجي مباشرةً، قد يتمكن من خداع تطبيقك لتحويل النص غير النشط إلى نص JavaScript قابل للتنفيذ وتنفيذه نيابةً عنه. تُعد eval() وFunction() وsetTimeout([string], ...) وsetInterval([string], ...) كلها متجهات قد يؤدي إدخال النص من خلالها إلى تنفيذ شيء ضار بشكل غير متوقع. تتمثل استجابة CSP الافتراضية لهذا الخطر في حظر كل هذه المتجهات تمامًا.

لهذا أكثر من بعض التأثيرات في طريقة إنشاء التطبيقات:

  • يجب تحليل JSON من خلال واجهة JSON.parse المضمَّنة بدلاً من الاعتماد على eval. تتوفّر عمليات JSON الأصلية في كل متصفّح منذ IE8، وهي آمنة تمامًا.
  • أعِد كتابة أي استدعاءات setTimeout أو setInterval تجريها حاليًا باستخدام الدوال المضمّنة بدلاً من السلاسل. مثلاً:
setTimeout("document.querySelector('a').style.display = 'none';", 10);

من الأفضل كتابتها على النحو التالي:

setTimeout(function () {
  document.querySelector('a').style.display = 'none';
}, 10);
  • تجنُّب استخدام النماذج المضمَّنة في وقت التشغيل: تستخدم العديد من مكتبات النماذج new Function() طوعًا لتسريع عملية إنشاء النماذج في وقت التشغيل. إنّها تطبيق رائع للبرمجة الديناميكية، ولكنها تنطوي على خطر تقييم النصوص الضارّة. تتوافق بعض أطر العمل مع سياسة CSP بطريقة غير تقليدية، وذلك بدلاً من استخدام محلّل لغوي فعّال في حال عدم استخدام eval. ويعدّ توجيه ng-csp الخاص بـ AngularJS مثالاً جيدًا على ذلك.

مع ذلك، قد يكون الخيار الأفضل هو استخدام لغة نموذجية توفّر ميزة التجميع المسبق (Handlebars تستخدم، على سبيل المثال). يمكن أن يؤدي التجميع المسبق للقوالب إلى جعل تجربة المستخدم أسرع من أسرع تنفيذ في بيئة التشغيل، كما أنه أكثر أمانًا أيضًا. إذا كان eval وأقواسه التي تستخدم النص إلى JavaScript ضروريين لتطبيقك، يمكنك تفعيلهما من خلال إضافة 'unsafe-eval' كمصدر مسموح به في توجيه script-src، ولكن لا ننصح بذلك بشدة. إنّ حظر القدرة على تنفيذ السلاسل يجعل من الصعب على المهاجم تنفيذ رمز غير مصرّح به على موقعك الإلكتروني.

إعداد التقارير

وقد يستفيد المستخدمون كثيرًا من قدرة سياسة CSP على حظر الموارد غير الموثوق بها من جهة العميل، ولكن قد يكون من المفيد إعادة إرسال نوع من الإشعارات إلى الخادم حتى تتمكن من رصد أي أخطاء تسمح بإدخال محتوى ضارّ في المقام الأول. لتحقيق هذه الغاية، يمكنك توجيه المتصفّح لإرسال POST بلاغات عن المخالفات بتنسيق JSON إلى موقع محدّد في التوجيه report-uri.

Content-Security-Policy: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;

ستبدو هذه التقارير على النحو التالي:

{
  "csp-report": {
    "document-uri": "http://example.org/page.html",
    "referrer": "http://evil.example.com/",
    "blocked-uri": "http://evil.example.com/evil.js",
    "violated-directive": "script-src 'self' https://apis.google.com",
    "original-policy": "script-src 'self' https://apis.google.com; report-uri http://example.org/my_amazing_csp_report_parser"
  }
}

تحتوي هذه الصفحة على جزء كبير من المعلومات التي ستساعدك في تتبُّع السبب المحدد للانتهاك، بما في ذلك الصفحة التي وقعت فيها المخالفة (document-uri) ومُحيل هذه الصفحة (يُرجى العلم أنّه على عكس حقل رأس HTTP، إنّ المفتاح ليس يحتوي على أخطاء إملائية) والمورد الذي انتهك سياسة الصفحة (blocked-uri) والتوجيه المحدّد الذي انتهكته (violated-directive) والسياسة الكاملة للصفحة (original-policy).

إعداد التقارير فقط

إذا كنت قد بدأت للتو باستخدام سياسة CSP، من المنطقي تقييم الحالة الحالية لتطبيقك قبل طرح سياسة صارمة للمستخدمين. وكخطوة أساسية لإجراء عملية نشر كاملة، يمكنك أن تطلب من المتصفّح مراقبة إحدى السياسات، والإبلاغ عن الانتهاكات، بدون فرض القيود. وبدلاً من إرسال عنوان Content-Security-Policy، يمكنك إرسال عنوان Content-Security-Policy-Report-Only.

Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;

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

الاستخدام في العالم الحقيقي

يمكن استخدام CSP 1 بشكلٍ كبير في Chrome وSafari وFirefox، لكنه لا يعمل إلا بصورة محدودة في IE 10. يمكنك الاطّلاع على التفاصيل على caniuse.com، لأنّ المستوى 2 من سياسة CSP أصبح متاحًا في Chrome منذ الإصدار 40. وقد نشرت مواقع إلكترونية ضخمة مثل Twitter وFacebook العنوان (دراسة الحالة على Twitter جديرة بالقراءة)، وهذا المعيار جاهز جدًا لبدء النشر على مواقعك الإلكترونية.

تتمثل الخطوة الأولى نحو صياغة سياسة لتطبيقك في تقييم الموارد التي تُحمِّلها. بمجرد أن تظن أن لديك التعامل مع كيفية تجميع العناصر في تطبيقك، عليك إعداد سياسة بناءً على تلك المتطلبات. لنستعرض بعض حالات الاستخدام الشائعة ونحدد أفضل طريقة يمكننا من خلالها دعم هؤلاء المستخدمين ضمن الحدود الوقائية لـ CSP.

حالة الاستخدام رقم 1: أدوات وسائل التواصل الاجتماعي

  • يشمل الزر 1+ في Google نصًا برمجيًا من https://apis.google.com ويتضمن <iframe> من https://plusone.google.com. أنت بحاجة إلى سياسة تتضمن هذين المصدرين لتضمين الزر. الحد الأدنى من السياسة هو script-src https://apis.google.com; child-src https://plusone.google.com. عليك أيضًا التأكّد من سحب مقتطف JavaScript الذي توفّره Google إلى ملف JavaScript خارجي. إذا كانت لديك سياسة مستندة إلى المستوى 1 وتستخدم frame-src يُشترط عليك المستوى 2 تغييرها إلى child-src. لم يعد ذلك ضروريًا في المستوى 3 من سياسة CSP.

  • يحتوي الزر "أعجبني" على Facebook على عدد من خيارات التنفيذ. ننصحك بالالتزام بالإصدار <iframe> لأنّه محمي بالحماية من بقية أجزاء موقعك الإلكتروني. وهي تتطلّب توجيه child-src https://facebook.com لتعمل بشكل سليم. يُرجى العِلم أنّ رمز <iframe> الذي يوفّره Facebook يحمّل تلقائيًا عنوان URL نسبيًا، وهو //facebook.com. عليك تغيير ذلك لتحديد HTTPS بشكل صريح: https://facebook.com. ليس هناك سبب لاستخدام HTTP إذا لم تكن مضطرًا لذلك.

  • يعتمد زر التغريدات في Twitter على إمكانية الوصول إلى نص برمجي وإطار، تتم استضافتهما على https://platform.twitter.com. (يعرض Twitter أيضًا عنوان URL نسبيًا بشكل تلقائي، ويمكنك تعديل الرمز لتحديد HTTPS عند نسخه/لصقه محليًا). يمكنك استخدام script-src https://platform.twitter.com; child-src https://platform.twitter.com طالما أنّك ستنقل مقتطف JavaScript الذي يقدّمه Twitter إلى ملف JavaScript خارجي.

  • وهناك منصات أخرى لها متطلبات مشابهة ويمكن التعامل معها بالطريقة نفسها. نقترح عليك ضبط default-src لـ 'none'، ومشاهدة وحدة التحكّم لتحديد الموارد التي يجب تفعيلها لكي تعمل الأدوات.

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

script-src https://apis.google.com https://platform.twitter.com; child-src https://plusone.google.com https://facebook.com https://platform.twitter.com

حالة الاستخدام رقم 2: التأمين

لنفترض للحظة أنك تدير موقعًا مصرفيًا وتريد التأكد من أنه لا يمكن تحميل سوى تلك الموارد التي كتبتها بنفسك. في هذا السيناريو، يمكنك البدء بسياسة تلقائية تحظر كل شيء تمامًا (default-src 'none')، ثم البناء على هذه النقطة.

لنفترض أنّ المصرف يحمّل جميع الصور والأنماط والنصوص البرمجية من شبكة توصيل المحتوى على https://cdn.mybank.net، ويتصل عبر XHR إلى https://api.mybank.com/ لسحب أجزاء مختلفة من البيانات. يتم استخدام الإطارات، ولكن فقط للصفحات المحلية على الموقع الإلكتروني (بدون استخدام أصول تابعة لجهات خارجية). لا يتضمّن الموقع الإلكتروني فلاش ولا خطوطًا أو أي عناصر إضافية. عنوان CSP الأكثر تقييدًا الذي يمكننا إرساله هو:

Content-Security-Policy: default-src 'none'; script-src https://cdn.mybank.net; style-src https://cdn.mybank.net; img-src https://cdn.mybank.net; connect-src https://api.mybank.com; child-src 'self'

حالة الاستخدام رقم 3: طبقة المقابس الآمنة فقط

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

Content-Security-Policy: default-src https:; script-src https: 'unsafe-inline'; style-src https: 'unsafe-inline'

على الرغم من تحديد https: في default-src، لا يكتسب النص البرمجي وتوجيهات النمط هذا المصدر تلقائيًا. يستبدل كل توجيه تمامًا الإعداد الافتراضي لهذا النوع المحدد من الموارد.

المستقبل

المستوى 2 من سياسة أمان المحتوى هو اقتراح مرشح. بدأت مجموعة عمل أمان تطبيقات الويب التابعة لـ W3C العمل على التكرار التالي الخاص بالمواصفات: المستوى 3 من سياسة أمان المحتوى.

إذا كنت مهتمًا بالنقاش حول هذه الميزات القادمة، يمكنك الاطّلاع على أرشيفات القائمة البريدية public-webappsec@ أو المشاركة بنفسك.

ملاحظات