نطاق فرعي للإدارة لا يوقف CSRF: أربعة فحوص قبل الإطلاق
اسم مضيف جديد أصل جديد، وغالبا الموقع نفسه، لذا تعبره كوكيز same-site ونماذج الإرسال البسيطة. افحص الرموز والبوابة والتصريح.
نقل واجهة الإدارة إلى admin.example.com تحسين حقيقي: يبعد كوكيز الإدارة عن الصفحات العامة، ويمنح التطبيقين مخبأين منفصلين، ويتيح توجيه سياسة شبكة أصرم إلى اسم مضيف واحد. لكنه ليس ضابطا ضد CSRF، ولا يجعل شيفرة الموقع العام آمنة لتركها مفتوحة أمام مسؤول مسجل الدخول. الفصل يغير ما يعده المتصفح حدا، لا ما يتحقق منه الخادم، لذا نفذ هذه الفحوص الأربعة قبل أن تعده منتهيا.
اقرأ الأصل والموقع ككلمتين مختلفتين
الأصل هو المخطط والمضيف والمنفذ، لذا فإن https://www.example.com و https://admin.example.com أصلان مختلفان. أما الموقع بمعنى SameSite فهو المخطط زائد النطاق القابل للتسجيل، لذا فإن هذين الاسمين عادة موقع واحد. هذا الفرق هو الفخ كله: سمة SameSite لن تساعدك عبر النطاقات الفرعية الشقيقة، لأن المتصفح لا يعد الطلب عبر موقع إطلاقا. وجّه واجهة الإدارة إلى نطاق قابل للتسجيل مختلف فعلا، مثل admin-example.net، فيصبح الطلب عبر موقع حقا، وهنا يبدأ SameSite=Lax أو Strict في أداء عمل يمكن الاعتماد عليه.
اختبره في المتصفح بدل الاستدلال عليه.
حمّل الموقع العام، وافتح أدوات المطور، وانظر أي الكوكيز يرفقها المتصفح بطلب موجه إلى مضيف الإدارة. إذا لم يكن للكوكي سمة Domain فهو مقصور على المضيف ويبقى على اسمه؛ وإذا حمل Domain=example.com فإنه ينتقل إلى كل شقيق، ولم يفدك النطاق الفرعي الجديد شيئا بخصوص ذلك الكوكي.
افصل بين قراءة الاستجابة وإرسال الطلب
تقيد سياسة الأصل الواحد قراءة الاستجابات عبر الأصول. وهي لا تمنع إرسال الطلب، ولا تمنع نموذج إرسال من حمل بيانات اعتماد يملكها المتصفح أصلا. الطلب البسيط، ذو نوع محتوى النموذج أو GET عادي، يسلَّم دون فحص تمهيدي؛ ثم يقرر CORS هل يجوز للسكربت المستدعي قراءة الجواب. إن CSRF يعيش كله على جانب الإرسال.
لهذا يحتاج الخادم فحصا صريحا للعمليات المغيرة للحالة. رمز مزامنة مرتبط بالجلسة، أو كوكي إرسال مزدوج يقارن على الخادم، يغطي الحالة؛ ومقارنة Origin أو Referer تستحق الإضافة كبوابة ثانية لا كالوحيدة، لأن ليس كل طلب يحمل الترويسة وليس كل وكيل يحفظها. إن إرشادات OWASP لمنع CSRF تعد SameSite طبقة واحدة بين عدة، ولهذا السبب تحديدا.
قرر ما تثبته بوابة الشبكة فعلا
قائمة السماح لمخرج VPN أمام مضيف الإدارة ضابط جيد وادعاء هوية ضعيف. إنها تثبت أن الطلب جاء من عنوان يمنحه VPN، وقد يتشاركه كل من على ذلك المخرج، ولا تقول شيئا عن الشخص أو الجهاز الذي يقف خلفه. عاملها كمرشح دخول لا كمصادقة.
أبقها مستقلة عن فحوص مستوى الطلب. إذا كانت قائمة السماح الشيء الوحيد بين مهاجم ونقطة نهاية تغير الحالة، فإن مسارا واحدا سيئ التهيئة أو عميل split-tunnel واحدا أو حاسوبا مستعارا واحدا يزيل الضابط كله.
سجل أيضا الرفض القادم من خارج النطاقات المتوقعة. اندلاعها هو أنفع إشارة على أن أحدهم يستكشف الحد الذي بنيته للتو، والصمت إشارة على أن المرشح لا يصل إليه شيء أصلا.
أبق الكوكيز وتسجيل الدخول والتصريح صريحة
نطاق الكوكي يقرر معظم النتيجة. كوكي النطاق الأب يرسل إلى مضيف الإدارة، فحقن سكربت في الموقع العام يستطيع التصرف بجلسة مسؤول؛ أما كوكي المضيف فلا. فضّل صيغة المضيف، وأضف سمة Secure، واستخدم بادئة __Host- حيث يدعمها النظام، لأن تلك البادئة تشترط Secure و Path=/ ولا سمة Domain. اقرأ ترويسة الاستجابة لا جرة الكوكيز: Set-Cookie: __Host-admin_session=...; Secure; Path=/; HttpOnly; SameSite=Lax، دون سمة Domain. المتصفح يطرح كوكي __Host- يحمل Domain، لذا فكوكي ما يزال يظهر على المضيفات الشقيقة دليل على أن البادئة لم تطبق قط.
ثم أبق التصريح على الخادم، لكل طلب، على كل نقطة نهاية إدارية لا عند تسجيل الدخول فقط. الطلب الآتي من شبكة مسموحة يجب أن يوثق ويصرح له بالعملية التي يطلبها؛ اسم المضيف ليس فاعلا. وإذا اشترك التطبيقان العام والإداري في تدفق دخول أو مخزن جلسات، فاكتب تلك العلاقة، لأنها أقصر طريق من علة في الموقع العام إلى إجراء إداري.
أعد فحص الحد بعد الفصل
نفذ الاختبارات السلبية لا المسار السعيد فقط: نموذج إرسال عبر موقع بلا رمز يجب أن يرفض، ورمز من جلسة أخرى يجب أن يرفض، ولا يجوز لأي GET أن يغير الحالة. افحص سمات الكوكي في أدوات المطور، وتأكد أن فحص Origin ينطلق عند طلب غير مطابق، وجرب مضيف الإدارة من خارج نطاق VPN لترى المرشح يعمل.
لا شيء من هذا يزيل ثغرة XSS داخل تطبيق الإدارة نفسه. اسم المضيف المنفصل حد عزل من جهة المتصفح له قيمة حقيقية، وليس بديلا عن منع تنفيذ الشيفرة غير الآمنة أو عن حماية الطلبات على الخادم. بعد الفصل تصبح القائمة أقصر مما تبدو: أصل مميز، وكوكيز مضيف فقط، ورمز على كل تعديل، ومرشح دخول لا تثق به كهوية، وتصريح يقرر لكل طلب.