البرمجة النصية عبر المواقع (XSS)

البرمجة النصية عبر المواقع (Cross-Site Scripting، XSS) عيب يُكتب فيه نص أدخله أحد المستخدمين في صفحة ويب بطريقة يقرؤها المتصفح على أنها HTML أو JavaScript لا نصاً. فالمتصفح لا يميّز سكربتاً كتبه المطورون من سكربت كتبه مهاجم في حقل تعليق، لذا تعمل الشيفرة المحقونة بجلسة الضحية: فتستطيع أن تقرأ ما يراه، أو تتصرف باسمه، أو تعيد رسم الصفحة. ويعدّ ⁦OWASP Top 10:2025⁩ هذا العيب جزءاً من فئة الحقن (Injection)، أي السبب الجذري نفسه الذي رأيته في حقن SQL في الدرس السابق، لكن المفسِّر هنا هو المتصفح.

مثال: يضبط عميل اسم العرض على qa7<b>x</b>qa7. تعرض صفحة الملف الشخصي الاسم كما كُتب تماماً لأن القالب رمّزه. أما في قائمة انتظار موظفي الدعم فيظهر الحرف x بخط عريض: فهذه الصفحة ألصقت الاسم داخل HTML مباشرةً، فأيّ سكربت يضعه أي عميل في اسم العرض قد يعمل في متصفح كل موظف دعم يفتح قائمة الانتظار.

لماذا يهم

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

وهو أيضاً عيب تكشفه بلا أدوات هجوم وبلا ضرر: علامة مميّزة تكتبها في حقل ونظرة إلى مصدر الصفحة تجيبان عن السؤال «هل تُعامَل هذه القيمة نصاً أم شيفرة HTML؟». ومعرفة الأنواع الثلاثة تخبرك أين تكتب العلامة وأين تبحث عنها.

XSS المنعكس والمخزَّن والمعتمد على DOM

لكل XSS الشكل نفسه: قيمة غير موثوقة تدخل من مصدر (source) وتصل إلى مَصبّ (sink) يفسّرها شيفرةً. وتختلف الأنواع في مكان انتظار القيمة ومن يحوّلها إلى شيفرة HTML، ويختبرها دليل OWASP لاختبار أمان الويب (WSTG) كلاً على حدة لأن الخطوات والأشخاص المعرّضين يختلفون.

XSS المنعكس (reflected): تنتقل القيمة في الطلب، عادةً في معامل استعلام أو حقل نموذج، وتعيدها الاستجابة فوراً، كما في «لا نتائج لـ…» في صفحة بحث. لا يراها إلا من أرسل الطلب، لذا يحتاج المهاجم إلى أن يجعل الضحية يرسل الطلب، عادةً بفتح رابط مُعدّ. XSS المخزَّن (stored): تُحفظ القيمة (مراجعة، تذكرة، حقل في الملف الشخصي، اسم ملف) وتُعرض لاحقاً لمستخدمين آخرين، ومنهم الموظفون. لا حاجة إلى رابط، وكل من يشاهدها معرّض، ولهذا هو الأشد خطورة عادةً. XSS المعتمد على DOM (DOM-based): استجابة الخادم نظيفة، لكن JavaScript الصفحة نفسها تقرأ مصدراً مثل location.search أو location.hash أو document.referrer أو حدث postMessage وتكتبه في مصبّ مثل innerHTML أو document.write أو eval. والجزء الذي يلي # في عنوان URL لا يُرسل إلى الخادم أبداً، لذا قد لا يترك هذا النوع أثراً في سجلات الخادم، ولا يصلحه أي ترميز في جهة الخادم.

XSS مخزَّن: قيمة فحص حفظها العميل A تعود داخل صفحة الموظف B؛ ومع ترميز HTML عند الإخراج يُعرض النص المخزَّن نفسه حرفياً.
  • دون ترميز المخرجات

    • العميل A حساب الاختبار الخاص بك
    • التطبيق الخادم وقاعدة البيانات
    • الموظف B متصفح بجلسة موظف
    1. 1 من العميل A إلى التطبيق: أرسل مراجعة تحمل قيمة الفحص title=qa7<b>x</b>qa7
    2. 2 التطبيق داخليًا: خزّن العنوان كما وصل تماماً التخزين ليس العيب: قاعدة البيانات تحفظ نصاً
    3. 3 من الموظف B إلى التطبيق: افتح قائمة انتظار المراجعات GET /agent/reviews
    4. 4 من التطبيق إلى الموظف B: HTML مبنيّ بإلصاق العنوان المخزَّن ردّ <td>qa7<b>x</b>qa7</td> فشل
    5. 5 الموظف B داخليًا: يفسّر المتصفح قيمة الفحص شيفرة HTML: x بخط عريض قد يعمل سكربت حقيقي هنا بجلسة الموظف فشل

    النتيجة: XSS مخزَّن: أي سكربت يكتبه أي عميل قد يعمل لدى كل موظف يفتح القائمة. فشل

  • مع ترميز المخرجات

    • العميل A حساب الاختبار الخاص بك
    • التطبيق الخادم وقاعدة البيانات
    • الموظف B متصفح بجلسة موظف
    1. 1 من العميل A إلى التطبيق: أرسل مراجعة تحمل قيمة الفحص title=qa7<b>x</b>qa7
    2. 2 التطبيق داخليًا: خزّن العنوان كما وصل تماماً التخزين ليس العيب: قاعدة البيانات تحفظ نصاً
    3. 3 من الموظف B إلى التطبيق: افتح قائمة انتظار المراجعات GET /agent/reviews
    4. 4 من التطبيق إلى الموظف B: يرمّز القالب العنوان أثناء كتابة الصفحة ردّ <td>qa7&lt;b&gt;x&lt;/b&gt;qa7</td> نجاح
    5. 5 الموظف B داخليًا: يعرض المتصفح الأحرف حرفياً نص الصفحة هو qa7<b>x</b>qa7؛ ولا يصبح شيء منه شيفرة HTML نجاح

    النتيجة: القيمة المخزَّنة نفسها غير ضارة لأنها تغادر الخادم نصاً. نجاح

Reflected  - travels in the request, echoed at once
  GET /search?q=qa7<b>x</b>qa7
  <h2>0 results for qa7<b>x</b>qa7</h2>

Stored     - saved now, rendered to someone else later
  POST /reviews        title=qa7<b>x</b>qa7
  GET  /agent/reviews  (agent B, next day)
  <td>qa7<b>x</b>qa7</td>

DOM-based  - server response clean, the page script writes it
  https://shop.example/help#qa7<b>x</b>qa7   (the part after # never reaches the server)
  status.innerHTML = 'Showing: ' + decodeURIComponent(location.hash.slice(1));

قيم فحص آمنة: هل القيمة نص أم شيفرة HTML؟

لست بحاجة إلى تشغيل سكربت لإثبات XSS. فالعيب هو «تُكتب مدخلات المستخدم في الصفحة دون ترميز»، وقيمة فحص آمنة (probe) ظاهرة وغير ضارة تثبته. ركّب قيمة الفحص من علامة مميّزة مثل qa7 مع الأحرف المؤثرة في HTML: < و> و" و' و&. وتتيح لك العلامة البحث في الصفحة المعروضة وفي مصدر HTML (أمر عرض مصدر الصفحة View Page Source، أو Ctrl+U) عن كل موضع وصلت إليه القيمة، بما فيها مواضع لم تتوقعها: <title>، وسمة (attribute)، ورسالة بريد، وتصدير CSV، ورسالة خطأ.

اقرأ النتيجة في المصدر لا على الشاشة فقط. فـqa7&lt;b&gt;x&lt;/b&gt;qa7 تعني أن القيمة رُمّزت بكيانات HTML وهي آمنة في ذلك الموضع؛ وqa7<b>x</b>qa7 بين الوسوم تعني أن شيفرة HTML قُبلت؛ وفي السمة تحقق هل أغلقت علامةُ الاقتباس التي كتبتها السمةَ. أما لوحة Elements فتعرض DOM لا المصدر: فيها تظهر القيمة الآمنة عقدةً نصية واحدة، بينما تظهر شيفرة HTML المقبولة عنصرَ b منفصلاً. ولا تستخدم قيمة فحص تنفيذية (executing probe)، وهي قيمة لا تفعل شيئاً سوى إظهار العلامة، إلا حين يحتاج الفريق إلى إثبات أن السكربت يعمل، وفي بيئة اختبار فقط، وبحساباتك أنت وبإذن مكتوب. وأزل القيم المخزَّنة بعد ذلك: فهي تبقى في قاعدة البيانات وتفاجئ زملاءك بعد أسابيع.

  • أدخل قيمة الفحص في كل مكان يمكن للمستخدم الكتابة أو الرفع فيه: النماذج، ومعاملات URL، وأسماء الملفات، والملفات المستوردة، وحقول API تعرضها صفحة لاحقاً، وترويسات الطلب التي يعكسها التطبيق مثل User-Agent أو Referer.
  • انظر إلى كل مخرج لا إلى المجاور للمدخل فقط: القوائم، وصفحات التفاصيل، وقوائم انتظار الإدارة، والإشعارات، والمعاينات، والنسخ المطبوعة أو PDF، وJSON الذي تضمّنه الصفحة في كتلة <script>.
  • في XSS المعتمد على DOM ضع قيمة الفحص في الجزء (fragment) بعد # وفي المعاملات التي تقرؤها JavaScript الصفحة، وراقب DOM في أدوات المطور لا استجابة الخادم.
  • لا تفحص أبداً نظاماً لا تملكه أو ليس لديك إذن مكتوب باختباره: فالفحص دون تصريح قد يخالف القانون حتى بلا سكربت، وقيمة الفحص المخزَّنة في الإنتاج يراها مستخدمون حقيقيون.
Probe                                 What a hit means
qa7<b>x</b>qa7                        "x" in bold: HTML text context is not encoded
qa7"'>x                               your quote closes the attribute in the source
qa7<script>alert('qa7')</script>      a script parsed from the response executes
qa7<img src=x onerror=alert('qa7')>   runs via innerHTML too, where <script> does not

Executing probes: test environment, own accounts, written permission, then remove.

جرّبها: مولّد مجموعات الأحرف الخاصة جرّبها: مرمّز URL

الدفاعات: ترميز المخرجات حسب السياق، والتنقية، وCSP

الدفاع الأساسي هو ترميز المخرجات (output encoding) بما يطابق السياق، وقد تعرّفت إليه في درس «التحقق من المدخلات وترميز المخرجات». والمهم في اختبار XSS هو المواضع التي يفشل فيها عادةً. أولاً، السياق الخاطئ: فكيانات HTML لا تحمي قيمة داخل كتلة <script> أو سمة معالج حدث مثل onclick أو داخل style، وتسمّي ورقة OWASP لمنع XSS (Cross Site Scripting Prevention Cheat Sheet) هذه المواضعَ سياقاتٍ خطرة (dangerous contexts) قد لا يمنع فيها الترميز وحده XSS، وتوصي بتمرير قيم المستخدم بوصفها بيانات لا بكتابتها داخل الشيفرة؛ والرابط الذي يقدّمه المستخدم في href يحتاج أيضاً إلى فحص مخطّطه (scheme) بقائمة سماح مثل https: فيُرفض javascript:، لأن الترميز يترك المخطّط كما هو. ثانياً، تجاوز الإعدادات الافتراضية: فمحركات القوالب وأطر العمل ترمّز نص HTML تلقائياً، لذا تختبئ العيوب في منافذ التجاوز فيها مثل dangerouslySetInnerHTML أو v-html أو الإسناد المباشر إلى innerHTML. ثالثاً، جهة المتصفح: ففي XSS المعتمد على DOM لا يشارك أي ترميز في الخادم، والإصلاح مصبّ آمن مثل textContent بدلاً من innerHTML.

يساعد التحقق من المدخلات (input validation) حيث يكون التنسيق صارماً (تاريخ، كمية) لكنه لا يغني عن الترميز: فالاسم O’Brien ورسالة تحتوي <3 ومنتج اسمه A&B كلها مشروعة. وحين يكون HTML نفسه ميزة، كما في تعليق بنص منسّق، يدمّره الترميز، ويكون الدفاع مُنقِّياً (sanitizer) بقائمة سماح يُبقي <b> و<a href> ويحذف السكربتات ومعالجات الأحداث.

سياسة أمان المحتوى (Content Security Policy، CSP) هي الطبقة الثانية. تخبر ترويسة الاستجابة Content-Security-Policy المتصفحَ أيّ السكربتات يجوز تشغيلها: فـscript-src 'self' تسمح بالسكربتات من أصل الموقع نفسه فقط، و'nonce-…' أو التجزئة (hash) تسمح بسكربتات مضمّنة بعينها، و'unsafe-inline' تسمح بتشغيل كل سكربت مضمّن وكل معالج حدث، فتعطّل هذه الحماية (وتتجاهلها المتصفحات الحالية إذا ذُكرت معها قيمة nonce أو تجزئة). ومع سياسة صارمة يُحظر <script> المحقون أو معالج onerror ويُسجَّل في وحدة التحكم، وهذا يحدّ من ضرر عيب الترميز دون أن يصلحه. اقرأ السياسة بأداة Security Header Analyzer أو HTTP Headers Parser وافحص script-src، أو default-src عند غيابها. وContent-Security-Policy-Report-Only تبلّغ عن المخالفات ولا تحظر شيئاً؛ وتستخدمها الفرق لتجربة سياسة قبل فرضها.

Where the value lands       Defect seen in the source         Defence
HTML text    <td>...</td>   <td>qa7<b>x</b>qa7</td>           HTML entity encoding
Attribute    value="..."    value="qa7"'>x"                   entities, quoted attribute
Link         href="..."     href="javascript:..."             allow-list the scheme
DOM sink     innerHTML      <b> rendered from location.hash   el.textContent = value
Rich text    comment        an onerror= attribute survives    allow-list sanitiser

Strict:  Content-Security-Policy: script-src 'self' 'nonce-R4nd0m'; object-src 'none'
Weak:    Content-Security-Policy: script-src 'self' 'unsafe-inline' *

جرّبها: مرمّز كيانات HTML جرّبها: محلّل ترويسات الأمان جرّبها: محلّل ترويسات HTTP

مثال تطبيقي: مراجعة تصل إلى مكتب الدعم

متجر يتيح للعملاء مراجعة المنتجات ويعرض المراجعات الجديدة لموظفي الدعم في قائمة انتظار. تختبر في بيئة Staging بحسابين، العميل A والموظف B، بإذن مكتوب من الفريق للفحوص الأمنية. بصفتك A ترسل مراجعة عنوانها qa7<b>x</b>qa7 ونصها qa7"'>x. تعرض صفحة المنتج العنوان حرفياً ومصدرها يحوي qa7&lt;b&gt;x&lt;/b&gt;qa7: مرمَّز. وبصفتك B تعرض قائمة الانتظار x بخط عريض ومصدرها يحوي <td>qa7<b>x</b>qa7</td>: XSS مخزَّن يصل إلى الموظفين. ويظهر نص المراجعة كما كُتب في الصفحتين. وتجيب صفحة البحث عن /search?q=qa7%3Cb%3Ex%3C%2Fb%3Eqa7 بـ«لا نتائج لـqa7x» وx بخط عريض: XSS منعكس. وتحمل كل استجابة Content-Security-Policy: script-src 'self' 'unsafe-inline'، فلن تمنع السياسة سكربتاً حقيقياً في أيّ من الموضعين.

  • الملاحظة ⁦1⁩، حرج (Critical): عناوين المراجعات تُعرض بوصفها HTML في قائمة انتظار الموظفين. الدليل: المدخل، وسطر المصدر، وكلا الدورين، ولقطة شاشة.
  • الملاحظة ⁦2⁩، رئيسي (Major): مصطلح البحث يُعاد بوصفه HTML في صفحة النتائج. الدليل: عنوان URL بالضبط وسطر المصدر.
  • الملاحظة ⁦3⁩، ثانوي (Minor، تحصين): تسمح CSP بسكربتات 'unsafe-inline' فلن تحدّ من الملاحظتين ⁦1⁩ و⁦2⁩.
  • اختبار التأكيد بعد الإصلاح: كرّر قيم الفحص وتوقّع الصيغة المرمَّزة في المصدر، وتحقق من أن عنواناً مشروعاً مثل Fast & cheap ما زال يُعرض كما كُتب لا بصيغة Fast &amp; cheap.

أخطاء شائعة

  • اختبار الحقل الذي تُدخل فيه القيمة فقط، لا كل صفحة ودور وتصدير يعرضها لاحقاً: فـXSS المخزَّن يعيش في المخرجات.
  • استخدام حِمل عام واحد مثل <script>alert(1)</script> في كل مكان: فمرشّح يحظر كلمة «script» يوقفه بينما تظل قيمة فحص بـ<b> تُعرض، ويبقى الترميز المفقود.
  • تشغيل قيم فحص تنفيذية أو مخزَّنة في الإنتاج، أو في بيئات مشتركة، أو في أنظمة ليس لديك إذن مكتوب باختبارها، وترك القيم المخزَّنة خلفك.
  • اعتبار التحقق في جهة العميل، أو طلب حظره جدار حماية تطبيقات الويب (WAF)، أو مخالفة CSP في وحدة التحكم دليلاً على إصلاح العيب.
  • فحص استجابة الخادم فقط بحثاً عن XSS المعتمد على DOM: فالجزء بعد # لا يصل إلى الخادم أبداً، فافحص DOM في المتصفح.
  • تسجيل CSP «موجودة» دون قراءة script-src: فسياسة فيها 'unsafe-inline' أو مضيف بحرف البدل (wildcard) لا تفعل الكثير ضد XSS.

من منظور ضمان الجودة

في الفريق، تنتمي فحوص XSS إلى الاختبار الوظيفي لكل ميزة تعرض نصاً من المستخدم، لا إلى مرحلة أمنية منفصلة: أضف قيمة الفحص ذات العلامة المميّزة إلى الاختبارات السلبية لكل نموذج، وحين تضيف قصة مستخدم نصاً منسّقاً أو معاينة أو تصديراً أو شاشة إدارية جديدة، اسأل في جلسة التنقيح كيف ستُرمَّز القيمة وهل يُتجاوز الترميز الافتراضي للقالب. اسأل المطورين أين يُستخدم innerHTML أو v-html أو dangerouslySetInnerHTML وأيّ مُنقٍّ يُطبَّق؛ واسأل فريق الأمان هل CSP مفروضة أم للإبلاغ فقط.

أبلغ عن الملاحظة كأي عيب مع إطار أمني: المدخل بالضبط، والصفحة والدور اللذان عُرضت فيهما بوصفها شيفرة HTML، والسطر من مصدر HTML، والبيئة، وترويسات الاستجابة، وتعليل الخطورة (من يراها وبأي جلسة). ولا ترفق استغلالاً عاملاً؛ ففريق الأمان يؤكد قابلية الاستغلال. وتحقق من الإصلاح بقيم الفحص نفسها مع قيمة مشروعة تحوي & وعلامات اقتباس، واسأل هل يُستخدم القالب نفسه في مكان آخر، فعيب الترميز نادراً ما يكون وحيداً.

تمرين عملي

خطّط لاختبارات XSS في أداة ملاحظات العملاء

المطلوب

ميزة لملاحظات العملاء منشورة في موقع Staging مصرّح لك باختباره؛ صفحاتها وترويسة الاستجابة موصوفة أدناه. لكل صفحة حدّد نوع XSS الذي قد تحمله، واكتب قيمة الفحص بالضبط وأين ستبحث عن العلامة، وصف النتيجة الآمنة، وقيّم CSP.

المادة
Staging site you are authorised to test: https://feedback.staging.example

Form    POST /feedback      fields: name, message
Pages   /wall               every name and message, shown to all visitors
        /admin/queue        new messages, shown to moderators (role: admin)
        /thanks?name=...    "Thank you, <name>" after submitting
        /wall#<id>          page script:
                              document.getElementById('status').innerHTML =
                                'Showing: ' + decodeURIComponent(location.hash.slice(1));

Response header on every page:
  Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'
الخطوات
  1. صنّف كل صفحة مرشّحةً لـXSS منعكس أو مخزَّن أو معتمد على DOM، واذكر من سيتعرض له.
  2. اكتب المدخل أو عنوان URL الذي ستستخدمه بالضبط مع العلامة qa7، وسمّ المخرج الذي ستفحصه.
  3. صف النتيجة الآمنة لكل صفحة كما ينبغي أن تظهر في مصدر HTML أو في DOM.
  4. اقرأ قيمة Content-Security-Policy وقرّر كيف تؤثر في الخطورة وما الذي يدخل في التقرير.
إظهار الإجابة النموذجية
الإجابة النموذجية

/wall و/admin/queue: مرشّحتان لـXSS مخزَّن؛ /wall تعرّض كل زائر و/admin/queue تعرّض المشرفين، وهذا أشد خطورة. من حسابك أنت أرسل إدخالين: أحدهما فيه qa7<b>x</b>qa7 في الحقلين، والآخر فيه qa7"'>x في الحقلين، كي يُفحص كل مخرج أياً كان الحقل الذي يعرضه، ثم افتح الصفحتين زائراً ومشرفاً. النتيجة الآمنة: يحوي المصدر qa7&lt;b&gt;x&lt;/b&gt;qa7، وتظهر علامة الاقتباس التي تقع داخل سمة بصيغة &quot;، وتعرض الصفحة الأحرف حرفياً. واحذف قيم الفحص المخزَّنة حين تنتهي.

/thanks?name=: مرشّحة لـXSS منعكس يعرّض كل من يفتح رابطاً مُعدّاً. افتح /thanks?name=qa7%3Cb%3Ex%3C%2Fb%3Eqa7 (قيمة الفحص مرمَّزة لعنوان URL) وافحص العنوان الرئيسي و<title>. النتيجة الآمنة: الصيغة المرمَّزة في المصدر، ويظهر Thank you, qa7<b>x</b>qa7 نصاً.

/wall#…: مرشّحة لـXSS معتمد على DOM يعرّض كل من يفتح رابطاً مُعدّاً. افتح /wall#qa7<b>x</b>qa7 وافحص العنصر status في لوحة Elements؛ فالخادم لا يستلم الجزء بعد # أبداً، لذا لا تثبت استجابته ولا سجلاته شيئاً. النتيجة الآمنة: يستخدم السكربت textContent (أو يرمّز قبل innerHTML) فتظهر الحالة Showing: qa7<b>x</b>qa7 حرفياً.

CSP: بما أن script-src موجودة فهي التي تحكم السكربتات لا default-src 'self'، وscript-src 'self' 'unsafe-inline' تسمح بتشغيل أي سكربت مضمّن، فلن تحدّ من سكربت محقون في أيّ من هذه الصفحات. أبلغ عنها ملاحظةَ تحصين منفصلة. وإذا أكدت قيم الفحص العيوب، فصنّف حالتي XSS المخزَّن حرجتين (Critical)، و/admin/queue أولاً لأن صلاحيات المشرفين أعلى، والحالتين المنعكسة والمعتمدة على DOM رئيسيتين (Major)، ولكل منها المدخل والموضع وسطر المصدر والدور.

أسئلة شائعة

هل <script>alert(1)</script> حِمل اختبار آمن؟

التنبيه نفسه غير ضار، لكن نسخة مخزَّنة منه تقاطع كل مستخدم يفتح الصفحة، والاختبار دون إذن قد يخالف القانون أياً كان الحِمل. ابدأ بقيمة فحص بشيفرة HTML مثل qa7<b>x</b>qa7 فهي تثبت الترميز المفقود نفسه؛ ولا تستخدم قيمة تنفيذية إلا في بيئة اختبار وبحساباتك وبإذن، وأزلها بعد ذلك.

إذا كان التحقق من المدخلات موجوداً، فهل يُمنع XSS؟

ليس بشكل موثوق. يرفض التحقق القيم الخاطئة بوضوح ويناسب التنسيقات الصارمة، لكن الأسماء والرسائل وعناوين المنتجات تحتوي بشكل مشروع على < و& وعلامات اقتباس، والقيم تصل أيضاً عبر API والاستيراد. والدفاع الذي يعمل في كل مكان هو الترميز حسب سياق المخرجات لحظة كتابة القيمة في الصفحة.

حظرت CSP قيمة الفحص. هل الصفحة آمنة؟

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

المراجع

  • OWASP Cheat Sheet Series: Cross Site Scripting PreventionOWASP Foundationمنع XSS: الترميز عند الإخراج بحسب كل سياق، وتعقيم HTML الذي يكتبه المستخدم، ومواضع الإدراج الآمنة في DOM وحمايات الأطر، مع اعتبار CSP طبقة دفاع إضافية فقط.
  • Cross Site Scripting (XSS)OWASP Foundationما هو هجوم XSS وأنواعه المنعكس والمخزّن وعبر DOM وكيف يمنعه الترميز.
  • OWASP Web Security Testing Guide (WSTG)OWASP Foundationالمنهجية المرجعية لاختبار تطبيقات الويب وواجهات API بحثاً عن نقاط الضعف الأمنية، اختباراً تلو الآخر.
  • Content-Security-Policy — MDNMDN Web Docs (Mozilla)توجيهات ترويسة CSP التي تقيّد المصادر التي يمكن تحميل السكربتات والأنماط والموارد الأخرى منها.

تدرّب بأدوات متقن

تهريب أحرف HTML الخاصة (< و> و& وعلامات الاقتباس) إلى كيانات لمنع هجمات XSS.

الترميز

ولّد مدخلات مليئة بالأحرف الخاصة: علامات الاقتباس، والأحرف الوصفية لـ SQL/HTML/JSON، وأحرف التحكم، والرموز التعبيرية، وحيل المسارات.

بيانات الاختبار

ترميز النص بالنسبة المئوية (percent-encoding) لاستخدامه بأمان في عناوين URL وسلاسل الاستعلام وبيانات النماذج.

الترميز

تقييم ترويسات أمان HTTP (CSP وHSTS وX-Frame-Options وReferrer-Policy وPermissions-Policy وCOOP/CORP) من ترويسات ملصقة أو عنوان URL عام.

التحقق

تحليل ترويسات طلبات واستجابات HTTP الخام إلى جدول منظّم مع الشروحات.

الويب

للتعمّق أكثر

تقدّمك في هذا الموضوع

جزء من مسار تعلم ضمان الجودة