معظم أمان أي موقع يسكن في شيفرته، لكن مجموعة صغيرة من ترويسات استجابة HTTP هي التي تقرر ما يرضى المتصفح أن يفعله بهذه الشيفرة بعد وصولها. هي الفرق بين وسم <script> مدسوس يُنفَّذ وآخر يرفض المتصفح تشغيله، وبين زيارة أولى تمر عبر HTTP غير مشفّر وزيارة تُرفَع إلى HTTPS قبل أن تغادر شريط العنوان.
وهي كذلك رخيصة التطبيق إلى حد غير مألوف. الترويسة إعداد لا شيفرة: أكثرها سطر واحد في خادم الويب أو شبكة التوزيع أو إطار العمل، وتنطبق على كل الاستجابات في وقت واحد. يغطي هذا الدليل ما تفعله كل ترويسة، وأيها يستحق ثمنه، وكيف تطبّق سياسة أمان المحتوى دون أن تعطّل موقعك نفسه، وكيف تتحقق من الذي ترسله اليوم.
لماذا تهم ترويسات الأمان
الترويسة تعليمة للمتصفح، والمتصفح هو الطرف الوحيد القادر على فرضها على جهاز المستخدم. وهذا يجعل الترويسات خط دفاع ثانياً يبقى صامداً حتى حين يكون شيء سابق قد أخطأ بالفعل:
- تحتوي أخطاءً وقعت منك بالفعل. سياسة أمان المحتوى لا تُصلح ثغرة XSS، لكنها قد تمنع السكربت المدسوس من العمل أو من إرسال أي شيء إلى الخارج.
- تغلق أصنافاً كاملة من الهجمات. سرقة النقر، والالتباس في نوع المحتوى، والعودة إلى HTTP ليست عيوباً في شيفرتك؛ إنها سلوكيات للمتصفح يجب أن تنسحب منها صراحة.
- توقف التسريب الصامت للبيانات. بدون سياسة للمُحيل، يسافر الرابط الكامل لصفحة خاصة إلى كل طرف ثالث تُحمِّل منه صورة.
- هي أول ما ينظر إليه المدقق. الترويسات الغائبة تظهر في كل فحص آلي واستبيان أمني ومراجعة مورّد، لأنها أرخص ملاحظة ممكنة.
والمأزق أنه يسهل جعلها «شبه صحيحة». سياسة CSP تحتوي unsafe-inline تمنع القليل جداً، وترويسة HSTS بمدة يوم واحد لا تحمي أحداً تقريباً. القيمة في التفاصيل.
الترويسات الأكثر أهمية
ست ترويسات تؤدي تقريباً كل العمل المفيد. وما تبقّى إما موروث، أو ضيق النطاق جداً، أو جاء ما يحل مكانه.
| الترويسة | ما تمنعه | الجهد |
|---|---|---|
Content-Security-Policy | XSS، وتسريب البيانات، وشيفرة طرف ثالث غير متوقعة | مرتفع |
Strict-Transport-Security | العودة إلى HTTP، وسرقة الكوكيز في أول طلب | منخفض |
X-Content-Type-Options | تنفيذ ملف مرفوع كأنه سكربت | ضئيل |
Referrer-Policy | تسريب الروابط الكاملة إلى أطراف ثالثة | ضئيل |
Permissions-Policy | الوصول إلى الكاميرا والميكروفون والموقع | منخفض |
Cross-Origin-Opener-Policy | هجمات عبر النوافذ من صفحات تفتحها | منخفض |
ابدأ من الأسفل. الترويسات الأربع الرخيصة سطر واحد لكل منها ولا تعطّل شيئاً تقريباً، فتستحق أن تُنشر اليوم؛ أما CSP فهي التي تحتاج خطة.
Content-Security-Policy
سياسة أمان المحتوى قائمة سماح تخبر المتصفح من أين يجوز أن يأتي كل نوع من الموارد. وتبدو سياسة صارمة بدرجة معقولة كما يلي:
default-src 'self'; script-src 'self' 'nonce-r4nd0m'; style-src 'self'; img-src 'self' data:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; object-src 'none'
اقرأها توجيهاً توجيهاً. default-src 'self' هو الخيار الاحتياطي: كل ما لم يُسمَّ صريحاً لا يُحمَّل إلا من أصلك أنت. وscript-src هو الأهم، لأن السكربتات هي ما يريد المهاجم تشغيله. وframe-ancestors 'none' يقول إنه لا يجوز لأي موقع آخر أن يضع صفحتك في إطار، وهو البديل الحديث لـ X-Frame-Options. وobject-src 'none' مع base-uri 'self' يغلقان منفذين قديمين لا يكلف إغلاقهما شيئاً.
قيمتان تحددان إن كانت سياستك حقيقية. فـ 'unsafe-inline' داخل script-src يسمح بأي <script> مضمَّن، بما في ذلك ما دسّه مهاجم، وهو بالضبط ما وُجدت CSP لمنعه. و'unsafe-eval' يسمح بـ eval() وأقاربها. والسياسة التي تحتوي أياً منهما تبقى مفيدة للتوجيهات غير المتعلقة بالسكربتات، لكنها لا تحميك من XSS.
المخرج هو nonce أو بصمة. الـ nonce قيمة عشوائية تُولَّد لكل استجابة وتُرفق بالترويسة وبكل <script nonce="..."> شرعي؛ فيشغّل المتصفح السكربتات التي تحمل تلك القيمة فقط، ولا يمكن لسكربت مدسوس أن يخمّنها. وتعمل البصمات بالطريقة نفسها مع السكربتات التي لا تتغير أبداً. وإن كان إطار عملك يُصدِر سكربتات مضمَّنة، فهو شبه قطعاً يدعم الـ nonce بالفعل، وتشغيله عادة مجرّد خيار في الإعدادات.
Strict-Transport-Security
تطلب HSTS من المتصفح أن يرفض HTTP غير المشفّر لنطاقك لفترة محددة، وهذا يغلق الفجوة التي يتركها التحويل وحده مفتوحة: فأول طلب على الإطلاق، قبل وصول التحويل، يسافر بلا تشفير ويمكن اعتراضه.
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
القيمة max-age بالثواني؛ والسنة هي الهدف المعتاد، وما دون بضعة أشهر لا يقدم كثيراً. وincludeSubDomains يمد القاعدة إلى كل نطاق فرعي، وهو ما يجعلها فعّالة وما يجدر التحقق منه أولاً كذلك: فأي نطاق فرعي ما زال يُقدَّم عبر HTTP سيتوقف. وpreload يطلب الإدراج في القائمة التي تأتي مع المتصفحات، فتُحمى حتى الزيارة الأولى.
تعامل مع HSTS كأمر يصعب التراجع عنه. فالمتصفح الذي رأى سياسة سنة كاملة سيفرضها سنة كاملة، مهما أرسلت بعد ذلك. طبّقها بـ max-age قصير، وتأكد أن شيئاً لم يتعطل، ثم ارفعها. ولأن HSTS لا معنى له إن كانت الشهادة خلفه غير صالحة، تحقق من الشهادة وتاريخ انتهائها بأداة فحص شهادة SSL قبل أن تلتزم بمدة طويلة.
الترويسات الصغيرة
هذه الأربع سطر واحد لكل منها ونادراً ما تكون موضع خلاف:
X-Content-Type-Options: nosniff— يمنع المتصفح من تخمين نوع الاستجابة من محتواها. وبدونه قد يُنفَّذ ملف رُفع بصيغة.txtكأنه سكربت إذا قرر المتصفح أنه يشبه ذلك.Referrer-Policy: strict-origin-when-cross-origin— يرسل الرابط الكامل إلى أصلك أنت، ويرسل الأصل فقط إلى مواقع HTTPS الأخرى، ولا يرسل شيئاً عند النزول إلى HTTP. هذا هو الإعداد الحديث الافتراضي، ويمنع تسريب المسارات والمعاملات الخاصة إلى أطراف ثالثة.Permissions-Policy: camera=(), microphone=(), geolocation=()— يوقف ميزات الجهاز التي لا يستخدمها موقعك، لصفحتك ولأي محتوى تضمّنه.Cross-Origin-Opener-Policy: same-origin— يقطع علاقة النافذة مع الصفحات التي تفتحها أو التي تفتحك، وهذا يمنع عائلة من الهجمات عبر النوافذ، وهو شرط مسبق لبعض ميزات العزل في المتصفح.
وما زال X-Frame-Options: DENY يستحق مكاناً في القائمة من أجل المتصفحات القديمة، لكن frame-ancestors في سياستك يحل مكانه وهو أقدر على التعبير. أرسل الاثنتين؛ فلا تعارض بينهما.
كيف تطبّق CSP بأمان
السياسة المكتوبة بالتخمين ستمنع شيئاً يحتاجه موقعك نفسه. ومسار «التقرير أولاً» يتجنب ذلك تماماً:
- انشر الترويسات الأربع الرخيصة اليوم.
nosniff، وسياسة للمُحيل، وسياسة للأذونات، وHSTS بـmax-ageقصير. ولا تعطّل أي منها عادة موقعاً يعمل. - أضف
Content-Security-Policy-Report-Only. البنية نفسها، لكن المتصفح يبلّغ عن الانتهاكات فقط بدلاً من منعها. ويبقى سلوك موقعك كما كان تماماً. - اجمع التقارير أسبوعاً أو أسبوعين. ستسمّي كل سكربت طرف ثالث، وخط، ونقطة تحليلات، ومعالج مضمَّن كنت قد نسيته. هذه هي الخطوة التي يتخطاها الناس، وهي التي تجعل ما بعدها بلا ألم.
- شدّد حتى تصمت التقارير. أضف المصادر التي تحتاجها فعلاً، واحذف ما تكتشف أنك لا تحتاجه. وقاوم توسيع توجيه إلى
*لإسكات تقرير واحد. - انتقل إلى التطبيق. أعِد تسمية الترويسة إلى
Content-Security-Policy، وأبقِ نسخة التقرير فقط جانبها لحين اختبار سياسة أصرم لاحقاً. - احذف
unsafe-inlineفي النهاية. هذا هو العمل الحقيقي: نقل السكربتات المضمَّنة إلى ملفات أو منحها قيم nonce. وكل ما قبل ذلك تحضير؛ وهذه هي الخطوة التي توقف XSS.
ملاحظة عملية: الترويسات تُضبط لكل استجابة، فاضبطها عند الحافة — شبكة التوزيع، أو الوسيط العكسي، أو وسيط إطار العمل — لا صفحةً صفحة. وضبطها في موضع واحد هو أيضاً الطريقة الوحيدة للتأكد أن صفحات الخطأ والتحويلات تحملها كذلك، وهي بالضبط المواضع التي تغيب عنها عادة.
ترويسات يمكنك التوقف عن إرسالها
بعض النصائح تقادمت بسوء، وإرسال ترويسة ميتة ليس بلا ضرر: فهو يضيف بايتات ويجعل التدقيق يبدو منتهياً وهو ليس كذلك.
X-XSS-Protection— مرشحات المتصفح التي كانت تتحكم بها لم تبقَ. لا تفعل شيئاً في أي متصفح حالي، والقيمة القديمةmode=blockأدخلت يوماً مشكلاتها الخاصة. احذفها واعتمد على CSP.Public-Key-Pins— أُزيلت HPKP من المتصفحات. كان من السهل أن تحجب نفسك عن نطاقك، ولهذا هُجرت.Expect-CT— شفافية الشهادات تُفرض الآن افتراضياً، فالترويسة زائدة.Feature-Policy— أُعيدت تسميتها إلىPermissions-Policyببنية مختلفة. أرسل الجديدة، ولا تُبقِ القديمة إلا إن كان عليك دعم شيء قديم جداً.
وفي المقابل، هناك ما يستحق الحذف فعلاً: المعلومات التي تتبرع بها. فترويسة Server أو X-Powered-By تذكر إصدار إطار عملك بدقة تخبر المهاجم أي ثغرات يجرّب أولاً. ليست ثغرة بحد ذاتها، لكن لا سبب لنشرها.
كيف تتحقق من ترويساتك
الترويسات علنية، لذا يستغرق التحقق من إعداد أي موقع ثوانٍ:
curl -I https://example.com. يطبع طلبHEADكل ترويسات الاستجابة دون تنزيل الصفحة. أضف-Lلتفحص الرابط النهائي بدل التحويل.- لوحة الشبكة في المتصفح. افتح أدوات المطور، وأعِد التحميل، واختر المستند الرئيسي، واقرأ قسم ترويسات الاستجابة. وتسجّل وحدة التحكم أيضاً كل انتهاك لـ CSP مع التوجيه الذي منعه، وهذا أسرع طريق لتنقيح سياسة.
- أداة فحص تقيّم النتيجة. تجلب أداة فحص ترويسات الأمان عندنا رابطاً وتبيّن أي الترويسات موجودة، وأيها غائب، وأين تكون ترويسة موجودة أضعف مما تبدو.
تحقق من أكثر من صفحتك الرئيسية. فالترويسات تُضبط غالباً على التطبيق الأساسي لا على مضيفات الملفات الثابتة أو صفحات الخطأ أو نطاقات الـ API الفرعية أو التحويل الذي يرسل www إلى النطاق الأصل. وبينما أنت هناك، تأكد أن سلسلة التحويل نفسها صحيحة؛ ويغطي مرجع رموز حالة HTTP أي رمز يناسب النقل الدائم.
لكتابة سياسة دون حفظ الصياغة، ابدأ من مولّد CSP لدينا، الذي ينبّهك أيضًا إلى الإعدادات التي تُضعفها.
أخطاء شائعة يجب تجنبها
- سياسة CSP تحتوي
unsafe-inlineفيscript-src. تجتاز معظم الفحوص الآلية ولا توقف XSS تقريباً. استخدم nonce أو بصمات. - توسيع توجيه إلى
*لإصلاح تقرير واحد. أضف الأصل المحدد بدلاً من ذلك؛ فـ*يتخلى عن التوجيه بالكامل. - HSTS بـ
max-ageطويل من اليوم الأول. هو عملياً غير قابل للتراجع طوال المدة التي نشرتها. ابدأ بمدة قصيرة. includeSubDomainsقبل تدقيق النطاقات الفرعية. كل ما بقي على HTTP، بما فيه الأدوات الداخلية، يتوقف عن التحميل.- ترويسات على التطبيق وليست على الحافة. تبقى صفحات الخطأ والتحويلات ومضيفات الملفات بلا حماية، وهي بالضبط الاستجابات التي يقصدها المهاجمون.
- ضبط الترويسة نفسها مرتين. ترويستا CSP تتقاطعان ولا تندمجان، فتكون النتيجة أصرم من كلتيهما وتعطّل شيئاً عادة؛ وقيمتان متعارضتان لـ
X-Frame-Optionsقد تُهملان كلياً. - الاستمرار في إرسال
X-XSS-Protectionواعتبار الأمر منتهياً. الترويسة الميتة تمنح طمأنينة زائفة في التقرير. - عدم تجاوز وضع التقرير فقط أبداً. التقارير التي لا تتصرف بناءً عليها لا تحمي أحداً.
تحقق من ترويساتك
ترويسات الأمان تمنح أفضل نسبة حماية إلى جهد متاحة على الويب: أربع منها سطر واحد لكل واحدة، والخامسة، CSP، هي في معظمها مسألة أن تُنصت إلى تقارير انتهاكاتك قبل أن تفرض أي شيء. ابدأ بالنظر في ما يرسله موقعك اليوم، وأضف الترويسات الرخيصة فوراً، ثم ضَع سياسة CSP في وضع التقرير فقط واترك لها أن تخبرك بما ينبغي أن تقوله سياستك.
أدوات وأدلة ذات صلة:
- أداة فحص ترويسات الأمان — اعرف أي الترويسات يرسلها رابط وأيها غائب.
- فحص شهادة SSL — تحقق من الشهادة خلف سياسة HSTS عندك.
- رموز حالة HTTP — تأكد أن تحويلك إلى HTTPS يعيد الرمز الصحيح.
- استعلام DNS: الدليل الكامل — السجلات خلف كل اسم مضيف في سياستك.
الأسئلة الشائعة
أي ترويسات الأمان أضيف أولاً؟⌄
ابدأ بالأربع التي لا تعطّل شيئاً تقريباً: X-Content-Type-Options: nosniff، وReferrer-Policy: strict-origin-when-cross-origin، وسياسة أذونات توقف ميزات الجهاز التي لا تستخدمها، وStrict-Transport-Security بمدة max-age قصيرة ترفعها لاحقاً. ثم أضف سياسة أمان المحتوى في وضع التقرير فقط، لأنها الوحيدة التي تحتاج مراقبة قبل الفرض.
هل تفيد سياسة CSP تحتوي unsafe-inline؟⌄
تفيد في كل شيء إلا الهجوم الذي تتفوق CSP في إيقافه. فتوجيهات مثل img-src وconnect-src وframe-ancestors وobject-src ما زالت تقيّد إلى أين تذهب البيانات ومن يستطيع تأطيرك. لكن 'unsafe-inline' في script-src يسمح بتشغيل أي سكربت مضمَّن مدسوس، فالسياسة لا تحميك من XSS. استبدله بـ nonce لكل استجابة أو ببصمات للسكربتات.
هل Strict-Transport-Security محفوف بالمخاطر؟⌄
المخاطرة أساساً في صعوبة التراجع: فالمتصفح الذي رأى max-age=31536000 سيرفض HTTP غير المشفّر لنطاقك سنة كاملة، مهما أرسلت بعد ذلك. طبّقه أولاً بمدة قصيرة، وتأكد أن كل نطاق فرعي يمكن الوصول إليه عبر HTTPS قبل إضافة includeSubDomains، وبعد ذلك فقط ارفع المدة وفكّر في preload.
ماذا حلّ مكان X-Frame-Options وX-XSS-Protection؟⌄
توجيه frame-ancestors في سياسة أمان المحتوى يحل مكان X-Frame-Options وهو أقدر على التعبير، مع أن إرسال الاثنتين لا يضر وما زال يفيد المتصفحات القديمة. أما X-XSS-Protection فلا بديل له لأن مرشحات المتصفح التي كان يتحكم بها أُزيلت؛ وCSP هي ما يوقف XSS الآن، ويمكن حذف الترويسة القديمة ببساطة.
أين ينبغي أن أضبط ترويسات الأمان؟⌄
عند الحافة وفي موضع واحد: شبكة التوزيع، أو الوسيط العكسي، أو وسيط إطار العمل. فضبطها صفحةً صفحة يترك صفحات الخطأ والتحويلات ومضيفات الملفات واستجابات الـ API بلا تغطية، وهي بالضبط الاستجابات التي تُنسى في التدقيق ويُقصد إليها في الهجوم.
كيف أعرف أي ترويسات يرسلها موقعي؟⌄
شغّل curl -I https://yourdomain.com مع إضافة -L لترى المقصد النهائي بدل التحويل، أو افتح لوحة الشبكة في المتصفح واقرأ ترويسات الاستجابة للمستند الرئيسي. وتفعل أداة فحص ترويسات الأمان ذلك من متصفحك، وتشير إلى الترويسات الغائبة وإلى الموجودة التي هي أضعف مما تبدو.
خبرة عملية تزيد على 15 عامًا في تطوير الويب وأمنه. يركّز على أمن الويب العملي: الحفاظ على المواقع آمنة وموثوقة وسهلة التشخيص. وُجد BuildToolForge ليجعل هذه الفحوصات مجانية وخاصة ومفهومة. تعمل الأدوات في متصفحك كلما أمكن، ولا يُخزَّن أي شيء تُدخله في أداة.
كيف نكتب أدلتنا: يُكتب كل دليل من خبرة عملية، ويُراجَع وفق المعايير الرسمية، ويُختبر بأدواتنا على نطاقات حقيقية، ونحدّثه عندما تتغير المعايير أو الأدوات. وجدت خطأً؟ راسلنا على contact@buildtoolforge.com.