الحدّ من النصوص البرمجية على المواقع الإلكترونية (XSS) من خلال تطبيق سياسة أمان المحتوى الصارمة (CSP)

دعم المتصفح

  • Chrome: 52.
  • الحافة: 79.
  • Firefox: 52.
  • Safari: الإصدار 15.4.

المصدر

البرمجة النصية على المواقع الإلكترونية (XSS)، إمكانية إدخال نصوص برمجية ضارة في أحد تطبيقات الويب أكبر ثغرات أمنية على الويب منذ أكثر من عقد.

سياسة أمان المحتوى (CSP) هي طبقة أمان إضافية تساعد على الحد من تأثير XSS. لإعداد سياسة أمان (CSP)، إضافة عنوان HTTP يتضمّن العنصر Content-Security-Policy إلى صفحة ويب وضبط القيم التحكم في الموارد التي يمكن لوكيل المستخدم تحميلها لتلك الصفحة.

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

مصطلح رئيسي: رقم غير مباشر هو رقم عشوائي يُستخدم مرة واحدة فقط ويمكنك استخدامه لوضع علامة العلامة <script> كموثوق بها

مصطلح رئيسي: دالة التجزئة هي دالة رياضية تحوّل مدخلاً. إلى قيمة عددية مضغوطة تُسمى تجزئة. يمكنك استخدام التجزئة (مثل SHA-256) لوضع علامة على مضمّن العلامة <script> كموثوق بها

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

لماذا يجب عليك استخدام سياسة أمان محتوى (CSP) صارمة؟

إذا كان موقعك الإلكتروني يستخدم سياسة أمان محتوى (CSP) تشبه script-src www.googleapis.com، فلن يكون فعالاً على مواقع متعددة يسمى هذا النوع من سياسة CSP القائمة المسموح بها CSP. إنها تتطلب الكثير من التخصيص ويمكن تجاوزها المهاجمون.

يمكن لـ CSPs الصارم استنادًا إلى أرقام التشفير أو أجزائها تجنُّب هذه المخاطر.

بنية سياسة CSP صارمة

تستخدم نهج أمان المحتوى الأساسي الصارم أحد استجابة HTTP التالية العناوين:

سياسة CSP الصارمة التي لا تستند إلى معايير

Content-Security-Policy:
  script-src 'nonce-{RANDOM}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';
طريقة عمل سياسة CSP الصارمة التي لا تستند إلى معايير

سياسة CSP الصارمة المستندة إلى التجزئة

Content-Security-Policy:
  script-src 'sha256-{HASHED_INLINE_SCRIPT}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';

تجعل الخصائص التالية سياسة CSP مثل هذه "صارمة" وبالتالي تكون آمنة:

  • تستخدم nonces 'nonce-{RANDOM}' أو تجزئات 'sha256-{HASHED_INLINE_SCRIPT}' للإشارة إلى علامات <script> التي يثق مطوِّر الموقع الإلكتروني في تنفيذها متصفح المستخدم.
  • تضبط 'strict-dynamic' تقليل الجهد المبذول في نشر سياسة أمان (CSP) لا تعتمد على التجزئة أو علامة تجزئة من خلال تلقائيًا يسمح بتنفيذ النصوص البرمجية التي ينشئها نص برمجي موثوق. هذا أيضًا إزالة حظر استخدام معظم مكتبات وأدوات JavaScript التابعة لجهات خارجية.
  • لا يستند إلى القوائم المسموح بها لعناوين URL، لذلك لا يتأثر تجاوزات سياسة CSP الشائعة.
  • تحظر هذه السياسة النصوص البرمجية المضمّنة غير الموثوق بها، مثل معالِجات الأحداث المضمّنة أو javascript:. معرّفات الموارد المنتظمة (URI).
  • تحظر هذه السياسة object-src لإيقاف المكوّنات الإضافية الخطيرة، مثل Flash.
  • تقيِّد هذه السياسة base-uri لحظر إدخال علامات <base>. وهذا يمنع للمهاجمين من تغيير مواقع النصوص البرمجية التي تم تحميلها من عناوين URL النسبية.

اعتماد سياسة أمان محتوى (CSP) صارمة

لاستخدام سياسة CSP صارمة، يجب:

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

يمكنك استخدام Lighthouse (الإصدار 7.3.0 والإصدارات الأحدث مع علامة --preset=experimental) تدقيق أفضل الممارسات خلال هذه العملية، للتحقّق مما إذا كان موقعك الإلكتروني يتضمّن سياسة CSP، وما إذا كان صارمة بما يكفي ليكون فعالاً ضد XSS.

منارة
  إبلاغ تحذيري بأنّه لم يتم العثور على سياسة CSP في وضع التنفيذ.
إذا كان موقعك الإلكتروني لا يتضمن سياسة أمان محتوى (CSP)، تعرض أداة Lighthouse هذا التحذير.

الخطوة 1: تحديد ما إذا كنت بحاجة إلى CSP مستند إلى علامة تجزئة أو غير مرتبط به

إليك طريقة عمل نوعَي سياسة CSP الصارمة:

سياسة أمان المحتوى (CSP) المستندة إلى الرقم

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

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

سياسة أمان المحتوى (CSP) المستندة إلى التجزئة

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

استخدام سياسة CSP مستندة إلى علامة التجزئة لصفحات HTML التي يتم عرضها بشكل ثابت أو الصفحات التي يجب مؤقتًا. على سبيل المثال، يمكنك استخدام سياسة CSP مستندة إلى علامة التجزئة لموقع ويب من صفحة واحدة. التطبيقات التي تم إنشاؤها باستخدام أطر عمل مثل Angular أو React أو غيرها، والتي تكون يتم عرضها بشكل ثابت بدون العرض من جهة الخادم.

الخطوة 2: إعداد سياسة CSP صارمة وإعداد نصوصك البرمجية

عند إعداد سياسة أمان (CSP)، يتوفر لك بعض الخيارات:

  • وضع إعداد التقارير فقط (Content-Security-Policy-Report-Only) أو وضع الفرض (Content-Security-Policy). وفي وضع إعداد التقارير فقط، لن يحظر سياسة أمان المحتوى (CSP) الموارد حتى الآن، لذلك لا يوجد شيء على موقعك، ولكن يمكنك رؤية الأخطاء للإبلاغ عن أي شيء كان سيتم حظره. محليًا، عندما إعداد سياسة أمان المحتوى (CSP)، فلا يهم حقًا، لأن كلا الوضعين يعرضان لك في وحدة تحكم المتصفح. ويمكن أن يساعدك "وضع التنفيذ"، إن وُجد، في العثور على الموارد التي ستحظرها سياسة CSP، نظرًا لأن حظر أحد الموارد قد يؤدي إلى تبدو الصفحة معطّلة. يصبح وضع "إعداد التقارير فقط" أكثر فائدة لاحقًا في هذه العملية (اطّلِع على الخطوة 5).
  • العنوان أو علامة HTML <meta> بالنسبة إلى التطوير المحلي، يمكن استخدام علامة <meta> بشكل أكبر طريقة ملائمة لتعديل سياسة CSP ومعرفة مدى تأثيرها على موقعك الإلكتروني بسرعة. في المقابل:
    • وعند نشر سياسة CSP في مرحلة الإنتاج لاحقًا، ننصحك بضبطها عنوان HTTP.
    • إذا كنت ترغب في تعيين سياسة CSP في وضع التقرير فقط، فستحتاج إلى تعيينه باعتباره لأن العلامات الوصفية CSP لا تتيح وضع التقارير فقط.

الخيار (أ): سياسة CSP المستندة إلى الرقم

إعداد استجابة HTTP التالية Content-Security-Policy في تطبيقك:

Content-Security-Policy:
  script-src 'nonce-{RANDOM}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';

إنشاء رقم nonce مع سياسة أمان المحتوى (CSP)

الرقم الخاص هو رقم عشوائي يتم استخدامه مرة واحدة فقط لكل عملية تحميل للصفحة. غير مستند إلى لا يمكن لـ CSP الحد من تأثير XSS إلا إذا لم يتمكن المهاجمون من تخمين قيمة nonce. حاسمة يجب أن تكون رسالة CSP الخاصة:

  • قيمة عشوائية قوية من الناحية المشفرة (يُفضل أن يكون طولها أكثر من 128 بت)
  • يتم إنشاؤه حديثًا لكل ردّ
  • تم ترميز Base64

في ما يلي بعض الأمثلة حول كيفية إضافة رقم CSP الخاص بأُطر العمل من جهة الخادم:

const app = express();

app.get('/', function(request, response) {
  // Generate a new random nonce value for every response.
  const nonce = crypto.randomBytes(16).toString("base64");

  // Set the strict nonce-based CSP response header
  const csp = `script-src 'nonce-${nonce}' 'strict-dynamic'; object-src 'none'; base-uri 'none';`;
  response.set("Content-Security-Policy", csp);

  // Every <script> tag in your application should set the `nonce` attribute to this value.
  response.render(template, { nonce: nonce });
});

إضافة سمة nonce إلى عناصر <script>

باستخدام سياسة أمان محتوى (CSP) لا تستند إلى أي مستخدم، يجب أن يكون كل عنصر <script> تحتوي على السمة nonce التي تطابق القيمة العشوائية الخاصة المحددة في عنوان CSP. يمكن أن تحتوي جميع النصوص البرمجية على نفس رقم خاص. الخطوة الأولى هي إضافة هذه السمات إلى جميع النصوص البرمجية حتى سياسة CSP تسمح لهم.

الخيار ب: عنوان استجابة CSP المستند إلى التجزئة

إعداد استجابة HTTP التالية Content-Security-Policy في تطبيقك:

Content-Security-Policy:
  script-src 'sha256-{HASHED_INLINE_SCRIPT}' 'strict-dynamic';
  object-src 'none';
  base-uri 'none';

بالنسبة إلى النصوص البرمجية المضمّنة المتعددة، تكون البنية كما يلي: 'sha256-{HASHED_INLINE_SCRIPT_1}' 'sha256-{HASHED_INLINE_SCRIPT_2}'

تحميل النصوص البرمجية التي مصدرها ديناميكيًا

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

مثال على كيفية تضمين النصوص البرمجية
تم السماح بواسطة سياسة أمان المحتوى (CSP).
<script>
  var scripts = [ 'https://example.org/foo.js', 'https://example.org/bar.js'];

  scripts.forEach(function(scriptUrl) {
    var s = document.createElement('script');
    s.src = scriptUrl;
    s.async = false; // to preserve execution order
    document.head.appendChild(s);
  });
</script>
للسماح بتشغيل هذا النص البرمجي، يجب حساب تجزئة النص البرمجي المضمّن وإضافته إلى عنوان استجابة CSP، بدلاً من {HASHED_INLINE_SCRIPT} . لتقليل عدد علامات التجزئة، يمكنك دمج جميع قيم التجزئة. النصوص في نص واحد. للاطلاع على ذلك عمليًا، يمكنك الرجوع إلى هذا مثال والرمز.
تم الحظر بواسطة سياسة أمان المحتوى (CSP).
<script src="https://example.org/foo.js"></script>
<script src="https://example.org/bar.js"></script>
تحظر سياسة CSP هذه النصوص البرمجية لأنه يمكن تجزئة النصوص البرمجية المضمّنة فقط.

اعتبارات تحميل النص البرمجي

يضيف مثال النص البرمجي المضمّن s.async = false لضمان يتم تنفيذ foo قبل bar، حتى إذا يتم تحميل bar أولاً. في هذا المقتطف: s.async = false لا يحظر المحلل اللغوي أثناء تحميل النصوص البرمجية، لأن النصوص البرمجية تتم إضافتها بشكل ديناميكي. يتوقف المحلل اللغوي فقط أثناء تنفيذ البرامج النصية، بالنسبة إلى نصَّين برمجيَين (async) ومع ذلك، باستخدام هذا المقتطف، ضع في اعتبارك ما يلي:

  • قد يتم تنفيذ أحد النصَّين البرمجيَين أو كليهما قبل انتهاء المستند. التنزيل. إذا كنت تريد أن يكون المستند جاهزًا بحلول الوقت تنفيذ النصوص البرمجية، يُرجى انتظار الحدث DOMContentLoaded قبل تقوم بإلحاق البرامج النصية. إذا تسبب هذا في مشكلة في الأداء لأن لا تبدأ النصوص البرمجية في التنزيل مبكرًا بما فيه الكفاية، استخدِم علامات التحميل المسبق في وقت سابق من الصفحة.
  • لا يتخذ "defer = true" أي إجراء. إذا كنت بحاجة إلى ذلك تلقائيًا، يمكنك تشغيل النص يدويًا عند الحاجة إليه.

الخطوة 3: إعادة ضبط نماذج HTML والرمز من جهة العميل

معالِجات الأحداث المضمّنة (مثل onclick="…" وonerror="…") ومعرّفات الموارد المنتظمة (URI) بلغة JavaScript يمكن استخدام (<a href="javascript:…">) لتشغيل النصوص البرمجية. وهذا يعني أن عندما يعثر على خطأ XSS، يمكنه إدخال هذا النوع من HTML وتنفيذ النصوص البرمجية الضارة. JavaScript. يحظر سياسة CSP المستندة إلى سمة لا تعتمد على الهوية أو المستندة إلى التجزئة استخدام هذا النوع من الترميز. إذا كان موقعك الإلكتروني يستخدم أيًا من هذه الأنماط، عليك إعادة ضبطها لتكون أكثر أمانًا. والبدائل.

إذا فعّلت سياسة CSP في الخطوة السابقة، ستتمكّن من الاطّلاع على انتهاكات سياسة CSP في وحدة التحكم في كل مرة تحظر فيها سياسة CSP نمطًا غير متوافق.

تقارير انتهاكات سياسة أمان المحتوى (CSP) في وحدة تحكُّم مطوّري برامج Chrome.
أخطاء وحدة التحكّم للرمز البرمجي المحظور

في معظم الحالات، يكون الحل مباشرًا:

إعادة ضبط معالِجات الأحداث المضمّنة

تم السماح بواسطة سياسة أمان المحتوى (CSP).
<span id="things">A thing.</span>
<script nonce="${nonce}">
  document.getElementById('things').addEventListener('click', doThings);
</script>
يتيح سياسة CSP استخدام معالِجات الأحداث المسجَّلة باستخدام JavaScript.
تم الحظر بواسطة سياسة أمان المحتوى (CSP).
<span onclick="doThings();">A thing.</span>
تحظر سياسة CSP معالِجات الأحداث المضمّنة.

إعادة ضبط معرّفات الموارد المنتظمة (URI) لـ javascript:

تم السماح بواسطة سياسة أمان المحتوى (CSP).
<a id="foo">foo</a>
<script nonce="${nonce}">
  document.getElementById('foo').addEventListener('click', linkClicked);
</script>
يتيح سياسة CSP استخدام معالِجات الأحداث المسجَّلة باستخدام JavaScript.
تم الحظر بواسطة سياسة أمان المحتوى (CSP).
<a href="javascript:linkClicked()">foo</a>
يحظر سياسة أمان المحتوى (CSP) JavaScript: معرّفات الموارد المنتظمة (URI).

إزالة eval() من JavaScript

إذا كان تطبيقك يستخدم eval() لتحويل تسلسلات سلسلة JSON إلى محتوى JavaScript. فيجب إعادة ضبط هذه الحالات على JSON.parse()، أسرع

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

يمكنك العثور على هذه الأمثلة والمزيد من الأمثلة لإعادة الهيكلة في سياسة CSP الصارمة هذه. codelab:

الخطوة 4 (اختيارية): إضافة إجراءات احتياطية لإتاحة إصدارات المتصفّح القديمة

دعم المتصفح

  • Chrome: 52.
  • الحافة: 79.
  • Firefox: 52.
  • Safari: الإصدار 15.4.

المصدر

إذا كنت بحاجة إلى دعم إصدارات المتصفّح القديمة:

  • لاستخدام strict-dynamic، يجب إضافة https: كإجراء احتياطي في وقت سابق. من Safari. وعند إجراء ذلك:
    • تتجاهل جميع المتصفّحات التي تتيح استخدام strict-dynamic الإجراء الاحتياطي https:، ولن يؤثّر ذلك في مدى قوة السياسة.
    • في المتصفحات القديمة، لا يمكن تحميل النصوص البرمجية المصدرة خارجيًا إلا إذا كانت واردة من مصدر HTTPS. يعد هذا أقل أمانًا من سياسة CSP الصارمة، ولكنه لا يزال ويمنع بعض أسباب XSS الشائعة، مثل حقن معرّفات الموارد المنتظِمة javascript:.
  • لضمان التوافق مع إصدارات المتصفِّح القديمة جدًا (أكثر من 4 سنوات)، يمكنك إضافة unsafe-inline كإجراء احتياطي تتجاهل جميع المتصفّحات الحديثة unsafe-inline. في حال توفّر nonce أو تجزئة سياسة CSP.
Content-Security-Policy:
  script-src 'nonce-{random}' 'strict-dynamic' https: 'unsafe-inline';
  object-src 'none';
  base-uri 'none';

الخطوة 5: نشر سياسة أمان المحتوى (CSP)

بعد التأكّد من أنّ سياسة أمان المحتوى (CSP) لا تحظر أي نصوص برمجية صالحة في تطوير البرامج المحلية، فيمكنك نشر سياسة أمان المحتوى (CSP) على مراحل، ثم إلى بيئة الإنتاج:

  1. (اختياري) يمكنك نشر سياسة CSP في وضع إعداد التقارير فقط باستخدام عنوان Content-Security-Policy-Report-Only وضع "إعداد التقارير فقط" سهل الاستخدام اختبار تغيير قد يؤدي إلى أعطال في عملية الإنتاج، مثل سياسة أمان محتوى (CSP) جديدة قبل بدء فرض قيود سياسة أمان المحتوى (CSP). في وضع "إعداد التقارير فقط"، لا يتضمن سياسة أمان المحتوى (CSP) تؤثر في سلوك التطبيق، ولكن لا يزال المتصفّح ينشئ أخطاءً في وحدة التحكّم وتقارير المخالفات عند مواجهتها أنماطًا غير متوافقة مع سياسة أمان المحتوى (CSP)، حتى تتمكن من معرفة ما كان يمكن أن يتعطل للمستخدمين النهائيين. لمزيد من المعلومات، معلومات، راجع واجهة برمجة التطبيقات لإعداد التقارير.
  2. إذا كنت واثقًا من أنّ سياسة CSP لن تؤدي إلى إيقاف موقعك الإلكتروني لدى المستخدمين النهائيين، نشر سياسة CSP باستخدام عنوان الاستجابة Content-Security-Policy. أر نقترح إعداد سياسة أمان المحتوى (CSP) باستخدام عنوان HTTP من جهة الخادم لأنها أكثر أكثر أمانًا من علامة <meta> بعد إكمال هذه الخطوة، يبدأ سياسة أمان المحتوى (CSP) حماية تطبيقك من بروتوكول XSS.

القيود

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

  • إذا لم يتم الرد على أي نص برمجي، ولكن هناك حقن مباشرة في النص أو مَعلمة src للعنصر <script> هذا.
  • إذا كان هناك حقن في مواقع النصوص البرمجية التي تم إنشاؤها ديناميكيًا (document.createElement('script'))، بما في ذلك أيّ دوال في المكتبة التي تنشئ عُقدًا DOM script استنادًا إلى قيم وسيطاتها. هذا النمط على بعض واجهات برمجة التطبيقات الشائعة مثل .html() في jQuery، بالإضافة إلى .get() .post() في jQuery < الإصدار 3.0
  • ما إذا كانت هناك عمليات حقن النماذج في تطبيقات AngularJS القديمة. مهاجم التي يمكنها إدخالها في نموذج AngularJS يمكنها استخدامه تنفيذ محتوى JavaScript عشوائي.
  • إذا كانت السياسة تتضمّن 'unsafe-eval'، الحقن في eval()، setTimeout()، وبعض واجهات برمجة التطبيقات الأخرى التي نادرًا ما يتم استخدامها.

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

محتوى إضافي للقراءة