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

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

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

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

TL;DR

  • استخدِم القوائم المسموح بها لإعلام العميل بما هو مسموح به وما هو غير مسموح به.
  • تعرَّف على التوجيهات المتاحة.
  • تعرَّف على الكلمات الرئيسية التي تأخذها.
  • يُعتبر الرمز المضمَّن و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

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

تسري السياسة على مجموعة كبيرة من الموارد.

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

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

  • يحدّ 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 التي يمكن تحميلها كعامل أو عامل مشترَك أو عامل خدمة. اعتبارًا من تموز (يوليو) 2 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 في مختلف الأدلة التعليمية على الويب. من الآن فصاعدًا، يجب تجاهل هذه الرؤوس التي تحتوي على بادئة. تتوافق المتصفّحات الحديثة (باستثناء Internet Explorer) مع عنوان Content-Security-Policy غير المزوّد ببادئة. هذا هو العنوان الذي يجب استخدامه.

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

قائمة المصادر في كل توجيه مرنة. يمكنك تحديد المصادر حسب المخطّط (data: أو https:)، أو حسب مدى التحديد من اسم المضيف فقط (example.com الذي يتطابق مع أي مصدر على هذا المضيف: أي مخطّط وأي منفذ) إلى معرّف الموارد المنتظم المؤهَّل بالكامل (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. يمكنك أيضًا استخدام مفتاح عشوائي أو تجزئة (راجِع المعلومات أدناه)، ولكن لا يُنصح بذلك. يُعدّ حظر النصوص البرمجية المضمّنة أكبر ميزة أمان يوفّرها إطار عمل CSP، ويؤدي حظر الأنماط المضمّنة إلى تعزيز أمان تطبيقك بالمثل. عليك بذل جهد بسيط في البداية لضمان عمل العناصر بشكل صحيح بعد نقل كل الرموز البرمجية خارج السطر، ولكن هذه المقايضة تستحق العناء.

إذا كان عليك استخدامها

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

لاستخدام مفتاح 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'

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

تعمل الوظائف الهاشتاغية بالطريقة نفسها تقريبًا. بدلاً من إضافة رمز إلى علامة النص البرمجي، أنشئ تجزئة 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 إلى توجيهك إلى حلول بلغات مختلفة. باستخدام الإصدار 40 من Chrome أو الإصدارات الأحدث، يمكنك فتح "أدوات مطوّري البرامج" ثم إعادة تحميل صفحتك. ستتضمّن علامة التبويب "وحدة التحكّم" رسائل خطأ تتضمّن تجزئة sha256 الصحيحة لكل نص برمجي مضمّن.

Eval أيضًا

حتى إذا لم يتمكّن المهاجم من حقن نص برمجي مباشرةً، قد يتمكّن من خداع تطبيقك لتحويل نص غير نشط إلى JavaScript قابل للتنفيذ وتنفيذه نيابةً عنه. إنّ eval() وnew 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 مثالاً جيدًا على ذلك.

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

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

إنّ قدرة بروتوكول CSP على حظر الموارد غير الموثوق بها من جهة العميل هي ميزة رائعة لمستخدمي تطبيقك، ولكن سيكون من المفيد جدًا تلقّي نوع من الإشعارات المُرسَلة مرة أخرى إلى الخادم حتى تتمكّن من تحديد أي أخطاء تسمح بالحقن الضار في المقام الأول وإصلاحها. لتحقيق هذا الغرض، يمكنك توجيه ال browser إلى 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).

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

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

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

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

الاستخدام في الحياة اليومية

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

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

حالة الاستخدام الأولى: التطبيقات المصغّرة لوسائل التواصل الاجتماعي

  • يتضمّن زر +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 من "خدمات إدارة المحتوى".

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

  • يعتمد زر التغريدة في Twitter على الوصول إلى نص وإطار، وكلاهما مستضافان على https://platform.twitter.com. (يقدّم Twitter أيضًا عنوان URL نسبيًا بشكلٍ default، ويمكنك تعديل الرمز لتحديد 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

حالة الاستخدام الثانية: فرض إجراءات إغلاق

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

لنفترض أنّ المصرف يحمّل كل الصور والأنماط والنصوص البرمجية من شبكة توصيل المحتوى (CDN) على العنوان 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@، أو يمكنك الانضمام إلى القائمة بنفسك.

ملاحظات