ترويسات أمان الموقع: ما هي وماذا تطلب من مطوّرك
ست ترويسات HTTP تُخبر المتصفح كيف يحمي زوار موقعك. ما تفعله كل واحدة، وكيف تفحص ترويسات موقعك، ونص جاهز تُرسله إلى مطوّرك.
حين يفتح أحدهم موقعك، يرسل الخادم إلى متصفحه الصفحة نفسها، ومعها بضعة أسطر من التعليمات لا يراها الزائر. هذه هي ترويسات HTTP. بعضها يُخبر المتصفح كيف يحمي من يتصفحون موقعك، كأن يتصل عبر اتصال مشفّر فقط، أو ألّا يشغّل سكربتات قادمة من عناوين مجهولة.
الترويسات لا تكلّف شيئًا، وتضبطها مرة واحدة. ومع ذلك تفتقر إليها مواقع كثيرة، لأن إعداد الخادم الافتراضي يتركها غالبًا. إذا قال لك فحص أمني إن موقعك «ينقصه ترويسات أمان»، فهذا المقال يشرح معنى ذلك، ويعطيك نصًا جاهزًا تُرسله إلى مطوّرك.
كيف ترى ما يرسله موقعك
أسرع طريقة هي متصفحك نفسه. في Chrome أو Edge أو Firefox افتح موقعك واضغط F12 (وعلى Mac اضغط Cmd+Option+I). تُفتح لوحة أدوات المطوّر. اختر تبويب Network وأعد تحميل الصفحة. ستجد في أعلى القائمة سطرًا بعنوان موقعك. انقر عليه وابحث عن قسم Response Headers.
تجاهل بقية اللوحة. أنت تبحث فقط عن الأسماء الواردة أدناه.
الطريقة الثانية أداة مجانية لفحص الترويسات، مثل فحص ترويسات الأمان (بالإنجليزية) لدينا، أو HTTP Observatory الذي تشغّله Mozilla على موقع MDN. تكتب عنوانك فتحصل على قائمة بالترويسات مع تقدير. اعتبر التقدير تلميحًا لا حكمًا.
Strict-Transport-Security: دائمًا HTTPS
تُخبر هذه الترويسة، واختصارها HSTS، المتصفحَ بما يلي: لفترة محددة، اتصل بهذا النطاق عبر HTTPS فقط. وهي تحمي مثلًا زوار شبكات Wi-Fi العامة، حيث قد يحاول أحدهم اعتراض ذلك الاتصال الأول غير المشفّر.
Strict-Transport-Security: max-age=31536000; includeSubDomains
max-age مدة بالثواني، وهي هنا سنة. وهنا الإشكال. حين يتذكر المتصفح هذه الترويسة، لا يعود بإمكان الزائر الذي يواجه مشكلة في الشهادة أن يتجاوز التحذير بنقرة. وincludeSubDomains تشمل كل نطاق فرعي، فإذا لم يكن لـshop.yourdomain.com أو لنطاق منسي مثل test.yourdomain.com اتصال HTTPS سليم، فسيتوقف فتحهما.
لذلك تبدأ بمدة قصيرة، يوم واحد مثلًا، وتمدّدها حين يعمل كل شيء. ولا تضف preload دون تفكير، لأن التراجع عنها صعب جدًا.
Content-Security-Policy: قائمة بالمصادر الموثوقة
هذه أقوى الترويسات، وهي الوحيدة التي قد تعطّل موقعك فعلًا. CSP قائمة بالأماكن التي يحق لصفحاتك أن تحمّل منها السكربتات والأنماط والصور والخطوط. فإذا نجح مهاجم في حقن سكربت خبيث، مثلًا عبر نموذج فيه ثغرة، يرفض المتصفح تشغيل شيفرة قادمة من عنوان ليس في القائمة.
المشكلة أن موقع شركة صغيرة نموذجيًا يعتمد على خدمات خارجية كثيرة: Google Analytics أو Tag Manager، وبكسل Facebook، ونافذة دردشة، وخريطة، وخطوط ويب، وفيديوهات YouTube، وبوابة دفع. إن تركتَ واحدة منها خارج القائمة توقف ذلك الجزء من الموقع عن العمل. تختفي الدردشة، أو يعجز العملاء عن الدفع.
لهذا يجب أن تبدأ CSP بوضع تجريبي، تحت اسم Content-Security-Policy-Report-Only. في هذا الوضع لا يحجب المتصفح شيئًا، بل يبلّغ فقط عمّا كان سيحجبه. يجمع مطوّرك هذه التقارير خلال أسبوع أو أسبوعين من الزيارات العادية، ويكمل القائمة، ثم يحوّل الترويسة إلى وضع التطبيق الفعلي. هكذا قد تبدو:
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' https://www.googletagmanager.com; img-src 'self' data: https:
هذا مثال توضيحي فقط. القائمة الحقيقية تعتمد على ما يستخدمه موقعك. وفي المواقع الكثيرة الإضافات قد يصعب إعداد CSP كاملة. حتى حينئذٍ، سياسة جزئية خير من لا شيء.
أربع ترويسات أقصر
X-Content-Type-Options: nosniff تُخبر المتصفح أن يثق بنوع الملف الذي يعلنه الخادم بدل أن يخمّنه. بدونها قد يُعامل ملف رُفع على أنه نص أو صورة كأنه سكربت في بعض الحالات. نادرًا ما تعطّل شيئًا، ما دام الخادم يعلن أنواع الملفات بشكل صحيح.
X-Frame-Options: SAMEORIGIN تمنع المواقع الأخرى من عرض موقعك داخل إطار. وهي تحمي من الاختطاف بالنقر (clickjacking): يحمّل أحدهم صفحتك بشكل غير مرئي تحت صفحته، ويخدع الزائر لينقر على شيء لا يراه، مثل زر الطلب. ومقابلها الأحدث هو frame-ancestors 'self' في CSP، ويمكنك ضبط الاثنتين معًا. وإذا كان موقعك مقصودًا أن يظهر داخل إطار في موقع آخر، كتقويم حجز في موقع شريك، فعلى مطوّرك أن يضيف عنوان ذلك الشريك إلى frame-ancestors.
Referrer-Policy: strict-origin-when-cross-origin تعني أنه حين ينقر أحدهم رابطًا من موقعك إلى موقع آخر، يعرف ذلك الموقع النطاق الذي جاء منه فقط، لا الصفحة. وهذا مهم حين تحتوي عناوين صفحاتك على شيء خاص، كرقم طلب. المتصفحات الحديثة تتصرف هكذا افتراضيًا، لكن ضبط الترويسة صراحةً لا يكلف شيئًا.
Permissions-Policy: camera=(), microphone=(), geolocation=() تعلن أن موقعك لا يستخدم الكاميرا ولا الميكروفون ولا الموقع الجغرافي. فلا يستطيع حتى سكربت محقون أن يطلب من الزائر الوصول إليها. وإذا كان في موقعك أداة «ابحث عن أقرب فرع» أو استشارات بالفيديو، فسيُبقي مطوّرك الميزة التي تحتاجها مفعّلة.
نص جاهز لمطوّرك
يمكنك نسخ النص التالي وإرساله كما هو، مع عنوانك.
Please add security headers to yourdomain.com,
on every page, including the admin panel and the shop:
Strict-Transport-Security: max-age=86400; includeSubDomains
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Content-Security-Policy-Report-Only: a policy matching
the scripts and services we actually use
Before enabling includeSubDomains, please check that
every subdomain works over HTTPS. If nothing breaks
within a week, please raise max-age to 31536000.
CSP in Report-Only mode first, for a week or two.
Then please send me the list of reported violations
and let's agree together when to switch to enforcing.
Please also tell me where the headers were set
(server config, .htaccess, Cloudflare or a plugin).
الطلب الأخير مهم. يمكن ضبط الترويسات في أكثر من مكان في الوقت نفسه، وإعدادان مختلفان للترويسة نفسها طريق سهل إلى الارتباك في المرة القادمة التي يتغير فيها شيء. وبعد تفعيلها افحص الترويسات مرة أخرى، وجرّب الأجزاء الأهم: نموذج الاتصال، وسلة الشراء، والدفع، والدردشة، والخريطة، وتسجيل الدخول إلى لوحة الإدارة.
ما لا تصلحه الترويسات
الترويسات خط دفاع ثانٍ. لن تصلح إضافة قديمة ولا كلمة مرور ضعيفة. هي تحدّ من الضرر حين يفشل شيء آخر.
ولا تطارد أعلى تقدير في أداة الفحص مهما كلّف الأمر. موقع فيه خمس ترويسات بسيطة ودفع يعمل أفضل حالًا بكثير من موقع فيه CSP مثالية توقف العملاء عن إتمام طلباتهم.
وأخيرًا: إذا نصحتك أداة بإضافة ترويسة X-XSS-Protection، فلا تعتبر ذلك أمرًا عاجلًا. أغلب المتصفحات الحديثة تتجاهلها، والنصيحة الحالية إما تركها أو ضبطها على 0.