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

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

تذكَّر أنّه يجب إعادة إنشاء قيم 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 الصحيحة لكل نص برمجي مضمّن.

التقييم أيضًا

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

ومع ذلك، سيكون الخيار الأفضل هو لغة النماذج التي توفّر ميزة compiling (تتوفّر هذه الميزة في 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 جديرة بالقراءة)، وهذا المعيار جاهز جدًا لبدء النشر على مواقعك الإلكترونية.

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

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

  • يشمل الزر 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@، أو الانضمام إلى القائمة بنفسك.

ملاحظات