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

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

جو ميدلي
جو ميدلي

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

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

تسلّط هذه النظرة العامة الضوء على الدفاع الذي يمكن أن يقلّل بشكل كبير من مخاطر هجمات 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. تم نشر مواصفات المستوى 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 التي يمكن تحميلها كعامل أو عامل مشترَك أو مشغّل خدمات. اعتبارًا من يوليو 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: وعناوين URL بـ <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>
// amazing.js
function doAmazingThings() {
    alert('YOU AM AMAZING!');
}
document.addEventListener('DOMContentLoaded', function () {
    document.getElementById('amazing')
    .addEventListener('click', doAmazingThings);
});

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

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

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

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

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

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

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

الآن، أضِف nonce إلى توجيه script-src الملحق بالكلمة الرئيسية nonce-.

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

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

تعمل علامات التجزئة بالطريقة نفسها. بدلاً من إضافة رمز إلى علامة النص البرمجي، يمكنك إنشاء تجزئة 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 مثالاً جيدًا على ذلك.

ومع ذلك، سيكون الخيار الأفضل هو لغة النموذج التي تقدم التجميع المسبق (على سبيل المثال، الإرشادات تفعل ذلك). يمكن أن يؤدي التجميع المسبق للنماذج إلى جعل تجربة المستخدم أسرع من التنفيذ الأسرع في وقت التشغيل، كما أنه أكثر أمانًا أيضًا. إذا كانت قيمة 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)، والتوجيه المحدّد الذي انتهك سياسة الصفحة (blocked-uri)، والسياسة الكاملة للصفحة (original-policy).violated-directive

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

إذا كنت قد بدأت للتو في استخدام سياسة 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. يتوفّر CSP المستوى 2 في Chrome منذ الإصدار 40. نشرت مواقع إلكترونية ضخمة مثل Twitter وFacebook العنوان (دراسة حالة Twitter تستحق القراءة)، والمعيار جاهز للغاية لبدء النشر على مواقعك الإلكترونية.

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

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@ أو الانضمام بنفسك.