دليل شامل لتعزيز أمان الواجهة الأمامية باستخدام سياسة أمان المحتوى (CSP) ومشاركة الموارد عبر المصادر (CORS)، لحماية تطبيقات الويب الخاصة بك من التهديدات الحديثة.
تقوية أمان الواجهة الأمامية: سياسة أمان المحتوى و CORS
في المشهد الرقمي المترابط اليوم، يعد أمان الواجهة الأمامية أمرًا بالغ الأهمية. أصبحت تطبيقات الويب مستهدفة بشكل متزايد من خلال هجمات متطورة، مما يجعل التدابير الأمنية القوية ضرورية. هناك مكونان حاسمان في بنية الواجهة الأمامية الآمنة هما سياسة أمان المحتوى (CSP) ومشاركة الموارد عبر المصادر (CORS). يقدم هذا الدليل الشامل نظرة متعمقة على هاتين التقنيتين، مع أمثلة عملية ورؤى قابلة للتنفيذ لمساعدتك في تحصين تطبيقات الويب الخاصة بك ضد التهديدات الحديثة.
ما هي سياسة أمان المحتوى (CSP)؟
سياسة أمان المحتوى (CSP) هي طبقة إضافية من الأمان تساعد في اكتشاف وتخفيف أنواع معينة من الهجمات، بما في ذلك هجمات البرمجة العابرة للمواقع (XSS) وهجمات حقن البيانات. يتم تنفيذ CSP عن طريق إرسال خادم الويب لترويسة استجابة HTTP باسم Content-Security-Policy إلى المتصفح. تحدد هذه الترويسة قائمة بيضاء بالمصادر المسموح للمتصفح بتحميل الموارد منها. من خلال تقييد مصادر المحتوى التي يمكن للمتصفح تحميلها، تجعل CSP من الصعب جدًا على المهاجمين حقن تعليمات برمجية ضارة في موقعك.
كيف تعمل سياسة أمان المحتوى (CSP)
تعمل CSP عن طريق توجيه المتصفح لتحميل الموارد (مثل النصوص البرمجية، أوراق الأنماط، الصور، الخطوط) من مصادر معتمدة فقط. يتم تحديد هذه المصادر في ترويسة CSP باستخدام التوجيهات. إذا حاول المتصفح تحميل مورد من مصدر غير مسموح به صراحةً، فسيقوم بحظر الطلب والإبلاغ عن انتهاك.
توجيهات CSP: نظرة عامة شاملة
تتحكم توجيهات CSP في أنواع الموارد التي يمكن تحميلها من مصادر محددة. إليك تفصيل لبعض أهم التوجيهات:
- default-src: يحدد المصدر الافتراضي لجميع أنواع المحتوى. هذا توجيه احتياطي يتم تطبيقه عندما لا تكون هناك توجيهات أخرى أكثر تحديدًا.
- script-src: يحدد المصادر التي يمكن تحميل النصوص البرمجية منها. هذا أمر حاسم لمنع هجمات XSS.
- style-src: يحدد المصادر التي يمكن تحميل أوراق الأنماط منها.
- img-src: يحدد المصادر التي يمكن تحميل الصور منها.
- font-src: يحدد المصادر التي يمكن تحميل الخطوط منها.
- media-src: يحدد المصادر التي يمكن تحميل الصوت والفيديو منها.
- object-src: يحدد المصادر التي يمكن تحميل المكونات الإضافية (مثل Flash) منها. غالبًا ما يتم تعيينه على 'none' لتعطيل المكونات الإضافية تمامًا بسبب مخاطرها الأمنية الكامنة.
- frame-src: يحدد المصادر التي يمكن تحميل الإطارات (مثل <iframe>) منها.
- connect-src: يحدد عناوين URL التي يمكن لوكيل المستخدم الاتصال بها باستخدام واجهات برمجة النصوص مثل XMLHttpRequest و WebSocket و EventSource.
- base-uri: يحدد عناوين URL التي يمكن استخدامها في عنصر <base> في المستند.
- form-action: يحدد عناوين URL التي يمكن إرسال عمليات إرسال النماذج إليها.
- upgrade-insecure-requests: يوجه وكيل المستخدم لترقية الطلبات غير الآمنة (HTTP) تلقائيًا إلى طلبات آمنة (HTTPS).
- report-uri: يحدد عنوان URL حيث يجب على المتصفح إرسال تقارير حول انتهاكات CSP. هذا التوجيه مهمل لصالح `report-to`.
- report-to: يحدد اسم مجموعة إبلاغ معرفة في ترويسة `Report-To`، حيث يجب على المتصفح إرسال تقارير حول انتهاكات CSP.
الكلمات الرئيسية لقائمة مصادر CSP
ضمن توجيهات CSP، يمكنك استخدام كلمات رئيسية لقائمة المصادر لتحديد المصادر المسموح بها. إليك بعض الكلمات الرئيسية الشائعة:
- 'self': يسمح بالموارد من نفس المصدر (النظام والمضيف) مثل المستند.
- 'none': يمنع الموارد من جميع المصادر.
- 'unsafe-inline': يسمح باستخدام النصوص البرمجية والأنماط المضمنة (مثل علامات <script> وسمات style). يجب استخدامه بحذر شديد لأنه يضعف بشكل كبير حماية CSP ضد XSS.
- 'unsafe-eval': يسمح باستخدام دوال تقييم الكود الديناميكي مثل
eval()وFunction(). يجب استخدامه بحذر شديد لأنه يقدم مخاطر أمنية كبيرة. - 'unsafe-hashes': يسمح بمعالجات أحداث مضمنة معينة أو علامات <style> تتطابق مع تجزئة محددة. يتطلب دعم المتصفح. استخدمه بحذر.
- 'strict-dynamic': يحدد أن الثقة الممنوحة صراحةً لنص برمجي موجود في الترميز، من خلال إرفاقه برقم nonce أو تجزئة، يجب أن تنتشر إلى جميع النصوص البرمجية التي يتم تحميلها بواسطة ذلك النص البرمجي الجذر.
- data: يسمح بـ data: URIs (مثل الصور المضمنة المشفرة كـ base64). استخدمه بحذر.
- https:: يسمح بتحميل الموارد عبر HTTPS من أي نطاق.
- [hostname]: يسمح بالموارد من نطاق معين (مثل example.com). يمكنك أيضًا تحديد رقم منفذ (مثل example.com:8080).
- [scheme]://[hostname]:[port]: عنوان URI مؤهل بالكامل، يسمح بالموارد من النظام والمضيف والمنفذ المحددين.
أمثلة عملية لـ CSP
دعنا نلقي نظرة على بعض الأمثلة العملية لترويسات CSP:
مثال 1: CSP أساسي مع 'self'
تسمح هذه السياسة بالموارد فقط من نفس المصدر:
Content-Security-Policy: default-src 'self'
مثال 2: السماح بالنصوص البرمجية من نطاق محدد
تسمح هذه السياسة بالنصوص البرمجية من نطاقك الخاص وشبكة توصيل محتوى موثوقة (CDN):
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com
مثال 3: تعطيل النصوص البرمجية والأنماط المضمنة
تمنع هذه السياسة النصوص البرمجية والأنماط المضمنة، وهو دفاع قوي ضد XSS:
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'
مهم: يتطلب تعطيل النصوص البرمجية المضمنة إعادة هيكلة HTML الخاص بك لنقل النصوص البرمجية المضمنة إلى ملفات خارجية.
مثال 4: استخدام Nonces للنصوص البرمجية المضمنة
إذا كان يجب عليك استخدام نصوص برمجية مضمنة، فاستخدم nonces (رموز عشوائية مشفرة تستخدم لمرة واحدة) لوضع علامات <script> المضمنة المحددة في القائمة البيضاء. هذا أكثر أمانًا من 'unsafe-inline'. يجب على الخادم إنشاء nonce فريد لكل طلب وتضمينه في كل من ترويسة CSP وعلامة <script>.
Content-Security-Policy: default-src 'self'; script-src 'nonce-r4nd0mN0nc3'; style-src 'self'
<script nonce="r4nd0mN0nc3"> console.log('Inline script'); </script>
ملاحظة: تذكر إنشاء nonce جديد لكل طلب. لا تعيد استخدام nonces!
مثال 5: استخدام Hashes للأنماط المضمنة
على غرار nonces، يمكن استخدام التجزئة (hashes) لوضع علامات <style> المضمنة المحددة في القائمة البيضاء. يتم ذلك عن طريق إنشاء تجزئة SHA256 أو SHA384 أو SHA512 لمحتوى النمط.
Content-Security-Policy: default-src 'self'; style-src 'sha256-HASHEDSTYLES'
<style sha256="HASHEDSTYLES"> body { background-color: #f0f0f0; } </style>
ملاحظة: التجزئة أقل مرونة من nonces لأن أي تغيير في محتوى النمط سيؤدي إلى إبطال التجزئة.
مثال 6: الإبلاغ عن انتهاكات CSP
لمراقبة انتهاكات CSP، استخدم توجيه report-uri أو report-to:
Content-Security-Policy: default-src 'self'; report-to csp-endpoint;
ستحتاج أيضًا إلى تكوين ترويسة Report-To. تحدد ترويسة Report-To مجموعة إبلاغ واحدة أو أكثر، والتي تحدد مكان وكيفية إرسال التقارير.
Report-To: {"group":"csp-endpoint","max_age":10886400,"endpoints":[{"url":"https://example.com/csp-report"}]}
اختبار ونشر CSP
يتطلب تنفيذ CSP تخطيطًا واختبارًا دقيقين. ابدأ بسياسة مقيدة وقم بتخفيفها تدريجيًا حسب الحاجة. استخدم ترويسة Content-Security-Policy-Report-Only لاختبار سياستك دون حظر الموارد. تبلغ هذه الترويسة عن الانتهاكات دون فرض السياسة، مما يسمح لك بتحديد المشكلات وإصلاحها قبل نشر السياسة في بيئة الإنتاج.
Content-Security-Policy-Report-Only: default-src 'self'; report-to csp-endpoint;
حلل التقارير التي ينشئها المتصفح لتحديد أي انتهاكات وتعديل سياستك وفقًا لذلك. بمجرد أن تكون واثقًا من أن سياستك تعمل بشكل صحيح، قم بنشرها باستخدام ترويسة Content-Security-Policy.
أفضل الممارسات لـ CSP
- ابدأ بـ default-src: حدد دائمًا
default-srcلإنشاء سياسة أساسية. - كن محددًا: استخدم توجيهات وكلمات رئيسية لقائمة المصادر محددة لتقييد نطاق سياستك.
- تجنب 'unsafe-inline' و 'unsafe-eval': تضعف هذه الكلمات الرئيسية CSP بشكل كبير ويجب تجنبها كلما أمكن ذلك.
- استخدم nonces أو hashes للنصوص البرمجية والأنماط المضمنة: إذا كان يجب عليك استخدام نصوص برمجية أو أنماط مضمنة، فاستخدم nonces أو hashes لوضع كتل التعليمات البرمجية المحددة في القائمة البيضاء.
- مراقبة انتهاكات CSP: استخدم توجيه
report-uriأوreport-toلمراقبة انتهاكات CSP وتعديل سياستك وفقًا لذلك. - اختبر بدقة: استخدم ترويسة
Content-Security-Policy-Report-Onlyلاختبار سياستك قبل نشرها في بيئة الإنتاج. - كرر وصقل: CSP ليس تكوينًا لمرة واحدة. راقب وصقل سياستك باستمرار للتكيف مع التغييرات في تطبيقك ومشهد التهديدات.
ما هي مشاركة الموارد عبر المصادر (CORS)؟
مشاركة الموارد عبر المصادر (CORS) هي آلية تسمح لصفحات الويب من مصدر (نطاق) واحد بالوصول إلى الموارد من مصدر مختلف. بشكل افتراضي، تفرض المتصفحات سياسة نفس المصدر (Same-Origin Policy)، والتي تمنع النصوص البرمجية من إجراء طلبات إلى مصدر مختلف عن المصدر الذي نشأ منه النص البرمجي. توفر CORS طريقة لتخفيف هذا القيد بشكل انتقائي، مما يسمح بالطلبات المشروعة عبر المصادر مع الحماية من الهجمات الخبيثة.
فهم سياسة نفس المصدر (Same-Origin Policy)
سياسة نفس المصدر هي آلية أمان أساسية تمنع نصًا برمجيًا خبيثًا من موقع ويب واحد من الوصول إلى البيانات الحساسة على موقع ويب آخر. يتم تعريف المصدر من خلال المخطط (البروتوكول)، والمضيف (النطاق)، والمنفذ. يكون لعنواني URL نفس المصدر إذا وفقط إذا كان لهما نفس المخطط والمضيف والمنفذ.
على سبيل المثال:
https://www.example.com/app1/index.htmlوhttps://www.example.com/app2/index.htmlلهما نفس المصدر.https://www.example.com/index.htmlوhttp://www.example.com/index.htmlلهما مصادر مختلفة (مخطط مختلف).https://www.example.com/index.htmlوhttps://sub.example.com/index.htmlلهما مصادر مختلفة (مضيف مختلف).https://www.example.com:8080/index.htmlوhttps://www.example.com:80/index.htmlلهما مصادر مختلفة (منفذ مختلف).
كيف تعمل آلية CORS
عندما تقوم صفحة ويب بإجراء طلب عبر المصادر، يرسل المتصفح أولاً طلبًا تمهيديًا (preflight) إلى الخادم. يستخدم الطلب التمهيدي طريقة HTTP OPTIONS ويتضمن ترويسات تشير إلى طريقة HTTP والترويسات التي سيستخدمها الطلب الفعلي. ثم يستجيب الخادم بترويسات تشير إلى ما إذا كان الطلب عبر المصادر مسموحًا به.
إذا سمح الخادم بالطلب، فإنه يتضمن ترويسة Access-Control-Allow-Origin في الاستجابة. تحدد هذه الترويسة المصدر (المصادر) المسموح لها بالوصول إلى المورد. ثم يتابع المتصفح الطلب الفعلي. إذا لم يسمح الخادم بالطلب، فإنه لا يتضمن ترويسة Access-Control-Allow-Origin، ويقوم المتصفح بحظر الطلب.
ترويسات CORS: نظرة مفصلة
تعتمد CORS على ترويسات HTTP للتواصل بين المتصفح والخادم. إليك أهم ترويسات CORS:
- Access-Control-Allow-Origin: تحدد المصدر (المصادر) المسموح لها بالوصول إلى المورد. يمكن أن تحتوي هذه الترويسة على مصدر محدد (مثل
https://www.example.com)، أو حرف بدل (*)، أوnull. استخدام*يسمح بالطلبات من أي مصدر، وهو أمر غير مستحسن بشكل عام لأسباب أمنية. استخدام `null` مناسب فقط لـ "الاستجابات المبهمة" كما هو الحال عند استرداد المورد باستخدام بروتوكول `file://` أو data URI. - Access-Control-Allow-Methods: تحدد طرق HTTP المسموح بها للطلب عبر المصادر (مثل
GET, POST, PUT, DELETE). - Access-Control-Allow-Headers: تحدد ترويسات HTTP المسموح بها في الطلب عبر المصادر. هذا مهم للتعامل مع الترويسات المخصصة.
- Access-Control-Allow-Credentials: تشير إلى ما إذا كان يجب على المتصفح تضمين بيانات الاعتماد (مثل ملفات تعريف الارتباط، ترويسات التفويض) في الطلب عبر المصادر. يجب تعيين هذه الترويسة على
trueللسماح ببيانات الاعتماد. - Access-Control-Expose-Headers: تحدد الترويسات التي يمكن كشفها للعميل. بشكل افتراضي، يتم كشف مجموعة محدودة فقط من الترويسات.
- Access-Control-Max-Age: تحدد المدة الزمنية القصوى (بالثواني) التي يمكن للمتصفح تخزين الطلب التمهيدي مؤقتًا.
- Origin: هذه ترويسة طلب يرسلها المتصفح للإشارة إلى مصدر الطلب.
- Vary: ترويسة HTTP عامة، ولكنها مهمة لـ CORS. عندما يتم إنشاء
Access-Control-Allow-Originديناميكيًا، يجب تضمين ترويسةVary: Originفي الاستجابة لتوجيه آليات التخزين المؤقت بأن الاستجابة تختلف بناءً على ترويسة طلبOrigin.
أمثلة عملية لـ CORS
دعنا نلقي نظرة على بعض الأمثلة العملية لتكوينات CORS:
مثال 1: السماح بالطلبات من مصدر محدد
يسمح هذا التكوين بالطلبات فقط من https://www.example.com:
Access-Control-Allow-Origin: https://www.example.com
مثال 2: السماح بالطلبات من أي مصدر (غير مستحسن)
يسمح هذا التكوين بالطلبات من أي مصدر. استخدمه بحذر لأنه يمكن أن يسبب مخاطر أمنية:
Access-Control-Allow-Origin: *
مثال 3: السماح بطرق وترويسات محددة
يسمح هذا التكوين بطرق GET و POST و PUT، وترويسات Content-Type و Authorization:
Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type, Authorization
مثال 4: السماح ببيانات الاعتماد
للسماح ببيانات الاعتماد (مثل ملفات تعريف الارتباط)، تحتاج إلى تعيين Access-Control-Allow-Credentials على true وتحديد مصدر معين (لا يمكنك استخدام * عند السماح ببيانات الاعتماد):
Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Credentials: true
تحتاج أيضًا إلى تعيين credentials: 'include' في طلب JavaScript fetch/XMLHttpRequest الخاص بك.
fetch('https://api.example.com/data', {
credentials: 'include'
})
طلبات CORS التمهيدية (Preflight)
لأنواع معينة من الطلبات عبر المصادر (مثل الطلبات ذات الترويسات المخصصة أو الطرق غير GET أو HEAD أو POST مع Content-Type من application/x-www-form-urlencoded أو multipart/form-data أو text/plain)، يرسل المتصفح طلبًا تمهيديًا باستخدام طريقة OPTIONS. يجب على الخادم الاستجابة للطلب التمهيدي بترويسات CORS المناسبة للإشارة إلى ما إذا كان الطلب الفعلي مسموحًا به.
إليك مثال على طلب تمهيدي واستجابة:
الطلب التمهيدي (OPTIONS):
OPTIONS /data HTTP/1.1
Origin: https://www.example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type, Authorization
الاستجابة التمهيدية (200 OK):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400
تحدد ترويسة Access-Control-Max-Age المدة التي يمكن للمتصفح فيها تخزين الاستجابة التمهيدية مؤقتًا، مما يقلل من عدد الطلبات التمهيدية.
CORS و JSONP
JSON مع الحشو (JSONP) هو أسلوب قديم لتجاوز سياسة نفس المصدر. ومع ذلك، يحتوي JSONP على مخاطر أمنية كبيرة ويجب تجنبه لصالح CORS. يعتمد JSONP على حقن علامات <script> في الصفحة، والتي يمكنها تنفيذ تعليمات برمجية عشوائية. توفر CORS طريقة أكثر أمانًا ومرونة للتعامل مع الطلبات عبر المصادر.
أفضل الممارسات لـ CORS
- تجنب استخدام *: تجنب استخدام حرف البدل (*) في ترويسة
Access-Control-Allow-Origin، لأنه يسمح بالطلبات من أي مصدر. بدلاً من ذلك، حدد المصدر (المصادر) المحددة المسموح لها بالوصول إلى المورد. - كن محددًا بالطرق والترويسات: حدد طرق HTTP والترويسات الدقيقة المسموح بها في ترويسات
Access-Control-Allow-MethodsوAccess-Control-Allow-Headers. - استخدم Access-Control-Allow-Credentials بحذر: قم بتمكين
Access-Control-Allow-Credentialsفقط إذا كنت بحاجة إلى السماح ببيانات الاعتماد (مثل ملفات تعريف الارتباط) في الطلبات عبر المصادر. كن على دراية بالآثار الأمنية للسماح ببيانات الاعتماد. - أمّن طلباتك التمهيدية: تأكد من أن خادمك يتعامل بشكل صحيح مع الطلبات التمهيدية ويعيد ترويسات CORS الصحيحة.
- استخدم HTTPS: استخدم دائمًا HTTPS لكل من المصدر والموارد التي تصل إليها عبر المصادر. هذا يساعد على الحماية من هجمات man-in-the-middle.
- Vary: Origin: إذا كنت تقوم بإنشاء ترويسة `Access-Control-Allow-Origin` ديناميكيًا، فقم دائمًا بتضمين ترويسة `Vary: Origin` لمنع مشكلات التخزين المؤقت.
سياسة أمان المحتوى (CSP) و CORS في الممارسة العملية: نهج مشترك
بينما تعالج كل من CSP و CORS المخاوف الأمنية، فإنهما يعملان في طبقات مختلفة ويوفران حماية تكميلية. تركز CSP على منع المتصفح من تحميل محتوى ضار، بينما تركز CORS على التحكم في المصادر التي يمكنها الوصول إلى الموارد على خادمك.
من خلال الجمع بين CSP و CORS، يمكنك إنشاء وضع أمان أكثر قوة لتطبيقات الويب الخاصة بك. على سبيل المثال، يمكنك استخدام CSP لتقييد المصادر التي يمكن تحميل النصوص البرمجية منها، و CORS للتحكم في المصادر التي يمكنها الوصول إلى نقاط نهاية واجهة برمجة التطبيقات (API) الخاصة بك.
مثال: تأمين واجهة برمجة تطبيقات (API) باستخدام CSP و CORS
لنفترض أن لديك واجهة برمجة تطبيقات مستضافة على https://api.example.com وتريد أن تكون قابلة للوصول فقط من https://www.example.com. يمكنك تكوين خادمك لإرجاع الترويسات التالية:
ترويسات استجابة API (https://api.example.com):
Access-Control-Allow-Origin: https://www.example.com
Content-Type: application/json
ويمكنك تكوين موقع الويب الخاص بك (https://www.example.com) لاستخدام ترويسة CSP التالية:
ترويسة CSP لموقع الويب (https://www.example.com):
Content-Security-Policy: default-src 'self'; script-src 'self'; connect-src 'self' https://api.example.com;
تسمح سياسة CSP هذه لموقع الويب بتحميل النصوص البرمجية والاتصال بواجهة برمجة التطبيقات، ولكنها تمنعه من تحميل نصوص برمجية أو الاتصال بنطاقات أخرى.
الخاتمة
تعتبر سياسة أمان المحتوى (CSP) ومشاركة الموارد عبر المصادر (CORS) أدوات أساسية لتقوية أمان تطبيقات الواجهة الأمامية الخاصة بك. من خلال تكوين CSP و CORS بعناية، يمكنك تقليل مخاطر هجمات XSS وهجمات حقن البيانات وغيرها من الثغرات الأمنية بشكل كبير. تذكر أن تبدأ بسياسة مقيدة، واختبر بدقة، وراقب وصقل تكوينك باستمرار للتكيف مع التغييرات في تطبيقك ومشهد التهديدات المتطور. من خلال إعطاء الأولوية لأمان الواجهة الأمامية، يمكنك حماية المستخدمين وضمان سلامة تطبيقات الويب الخاصة بك في العالم الرقمي المعقد بشكل متزايد اليوم.