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