Rails/security

من موسوعة حسوب

تأمين تطبيقات ريلز

يصف هذا الدليل مشاكل الأمان الشائعة في تطبيقات الويب وكيفية تجنبها باستخدام ريلز. بعد قراءة هذا الدليل، ستتلعم:

  • جميع التدابير المضادة التي سيسلط الضوء عليها.
  • مفهوم الجلسات (sessions) في ريلز، و ما يُنفذ في وجود وسائل الهجوم المعروفة.
  • كيف يمكن أن يكون مجرد زيارة أحد المواقع مشكلة أمنية (مع CSRF).
  • ما عليك الانتباه عند العمل مع الملفات أو توفير واجهة إدارة.
  • كيفية إدارة المستخدمين: تسجيل الدخول والخروج وهجمات الطرق على جميع الطبقات.
  • أكثر الطرق المعروفة لهجوم الحقن.

المقدمة

تعمل إطارات تطبيقات الويب لمساعدة المطورين على بناء تطبيقات الويب. كما يساعد بعضها أيضًا في تأمين تطبيق الويب. في الواقع، لا يكون إطار واحد أكثر أمانًا من الآخر: إذا كنت تستخدمه بشكل صحيح، فستتمكن من إنشاء تطبيقات آمنة مع العديد من الأطر. لدى ريلز بعض التوابع المساعدة الذكية، على سبيل المثال ضد حقن SQL، بحيث لا يعد هذا مشكلة.

بشكل عام لا يوجد شيء مثل مكونات الأمن سهلة الإستخدام. يعتمد الأمن على الأشخاص الذين يستخدمون الإطار، وأحيانًا على طريقة التطوير. ويعتمد ذلك على جميع طبقات بيئة تطبيقات الويب: التخزين الخلفي (back-end storage) وخادم الويب وتطبيق الويب نفسه (وربما طبقات أو تطبيقات أخرى).

ومع ذلك، تقدر مجموعة غارتنر (Gartner Group) أن 75٪ من الهجمات موجودة على طبقة تطبيقات الويب، ووجدت أن "من بين 300 موقع مدقق، 97٪ منهم عرضة للهجوم". وذلك لأن من السهل نسبيًا استخدام تطبيقات الويب، حيث يسهل فهمها والتعامل معها، حتى من قبل الشخص العادي.

تتضمن التهديدات ضد تطبيقات الويب سرقة حساب المستخدم ، أو تجاوز التحكم في الوصول، أو قراءة أو تعديل البيانات الحساسة، أو عرض محتوى احتيالي. أو قد يتمكن أحد المهاجمين من تثبيت برنامج حصان طروادة (Trojan horse program) أو برنامج إرسال بريد إلكتروني غير مرغوب فيه، ويهدف إلى الإثراء المالي أو التسبب في تلف اسم العلامة التجارية عن طريق تعديل موارد الشركة. من أجل منع الهجمات وتقليل تأثيرها وإزالة نقاط الهجوم، عليك أولاً وقبل كل شيء أن تفهم تماما أساليب الهجوم من أجل إيجاد الإجراءات المضادة الصحيحة. هذا ما يهدف إليه هذا الدليل.

من أجل تطوير تطبيقات الويب الآمنة، يجب عليك مواكبة جميع الطبقات ومعرفة أعدائك. لمواكبة الاشتراك في قوائم بريدية أمنية، اقرأ مدونات الأمان وأجري عمليات الفحص والتحديثات الأمنية بشكل دوري (راجع فصل "الموارد الإضافية" في الأسفل). يُعمل ذلك يدويا لأن هذا هو كيف تجد مشاكل أمنية منطقية سيئة.

الجلسات

المكان لجيد لبدء البحث عن الأمان هو الجلسات، والتي يمكن أن تكون عرضةً لهجمات معينة.

ما هي الجلسات؟

ملاحظة: البروتوكول HTTP هو بروتوكول عديم الحالة. الجلسات تجعله ذي حالة (stateful).

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

عادةً ما تتكون الجلسة من جدول Hash من القيم ومعرف الجلسة، ,عادة ما تتكون من سلسلة 32 حرف، لتحديد ذلك الجدول. يتضمن كل ملف تعريف ارتباط (cookie) يُرسَل إلى متصفح العميل معرف الجلسة. وفي الاتجاه الآخر: يرسل المتصفح إلى الخادم كل طلب من العميل. في ريلز، يمكنك حفظ واسترجاع القيم باستخدام التابع session:

session[:user_id] = @current_user.id
User.find(session[:user_id])

معرف الجلسة

ملاحظة: معرف جلسة العمل عبارة عن سلسلة ست عشرية عشوائية تتكون من 32 محرف.

تُنشأ معرّف جلسة العمل باستخدام SecureRandom.hex الذي ينشئ سلسلة ست عشرية عشوائية باستخدام توابع خاصة بالمنصة (مثل OpenSSL أو ‎/dev/urandom أو Win32 CryptoAPI) لإنشاء أرقام عشوائية آمنة مشفرة. في الوقت الحالي ليس من الممكن إجهاض المعرفات الخاصة بجلسات ريلز.

اختطاف الجلسة

تحذير: يتيح سرقة معرف جلسة المستخدم لمهاجم استخدام تطبيق الويب باسم الضحية.

تحتوي العديد من تطبيقات الويب على نظام الاستيثاق: يوفر المستخدم اسم مستخدم وكلمة مرور، ويفحصهما تطبيق الويب ثم يخزن معرف المستخدم المقابل في جدول Hash للجلسة. من الآن فصاعدا، الجلسة صالحة. في كل طلب، سيحمل التطبيق المستخدم المحدد بواسطة معرف المستخدم في الجلسة، دون الحاجة إلى استيثاق جديد. يحدد معرف الجلسة في ملف تعريف الارتباط جلسة العمل.

بعد ذلك، فإن ملف تعريف الارتباط بمثابة استيثاق مؤقت لتطبيق الويب. أي شخص يستغل ملف تعريف ارتباط من شخص آخر قد يستخدم تطبيق الويب باسم هذا المستخدم - مع احتمال حدوث عواقب وخيمة. في ما يلي بعض الطرق لاختطاف جلسة، وإجراءاتها المضادة:

  • تحسس ملف تعريف الارتباط (cookie) في شبكة غير آمنة. يمكن أن تكون الشبكة المحلية اللاسلكية مثالًا على مثل هذه الشبكة. في شبكة LAN لاسلكية غير مشفرة، من السهل جدًا الاستماع إلى حركة مرور جميع العملاء المتصلين. بالنسبة إلى أداة إنشاء تطبيقات الويب ، فهذا يعني توفير اتصال آمن عبر طبقة المقابس الآمنة. في ريلز 3.1 والإصدارات الأحدث، تحقق ذلك عن طريق فرض اتصال SSL دائمًا في ملف تهيئة التطبيق الخاص بك:
config.force_ssl = true
  • معظم الناس لا يمسحون ملفات تعريف الارتباط بعد العمل في أماكن عامة (مثل مقاهي الإنترنت). لذلك، إذا لم يسجل المستخدم الأخير الخروج من تطبيق ويب، فسيتمكن غيره من استخدامه باسم هذا المستخدم. قدم للمستخدم زر تسجيل الخروج في تطبيق الويب، واجعله بارزًا.
  • تهدف العديد من عمليات استغلال البرامج النصية عبر المواقع (XSS) إلى الحصول على ملف تعريف الارتباط الخاص بالمستخدم. ستقرأ المزيد عن XSS لاحقًا.
  • بدلاً من سرقة ملف تعريف ارتباط غير معروف للمهاجم، يجري إصلاح مُعرِّف جلسة المستخدم (في ملف تعريف الارتباط) المعروف لهم. اقرأ المزيد حول ما يسمى بتثبيت الجلسة لاحقًا.

الهدف الرئيسي لمعظم المهاجمين هو كسب المال. تتراوح الأسعار السرية لحسابات تسجيل الدخول المسروقة للبنوك من 10 إلى 1000 دولار (اعتمادًا على المبلغ المتاح للأموال)، و 0.40 إلى 20 دولارًا لأرقام بطاقات الائتمان، و 1 إلى 8 دولارات لحسابات مواقع المزادات على الإنترنت، و 4 - 30 دولارًا لكلمات مرور البريد الإلكتروني، وفقًا لتقرير تهديد أمن الإنترنت العالمي من سيمانتك.

إرشادات الجلسة

فيما يلي بعض الإرشادات العامة حول الجلسات.

  • لا تخزن أشياءً كبيرةً في جلسة واحدة. بدلًا من ذلك، يجب تخزينها في قاعدة البيانات وحفظ معرّفها في الجلسة. سيؤدي ذلك إلى التخلص من صداع التزامن ولن يملأ مساحة التخزين الخاصة بالجلسة (حسب سعة التخزين التي اخترتها، انظر أدناه). ستكون هذه فكرة جيدة أيضًا، إذا قمت بتعديل بنية كائن وما زالت الإصدارات القديمة منه موجودةً في ملفات تعريف الارتباط الخاصة بمستخدم ما. من خلال تخزين جلسات من جانب الخادم، يمكنك مسح الجلسات، ولكن مع التخزين من جانب العميل، يكون من الصعب التخفيف من ذلك.
  • يجب عدم تخزين البيانات المهمة في الجلسة. إذا مسح المستخدم ملفات تعريف الارتباط الخاصة به أو أغلق المتصفح، فستُفقَد البيانات. أضف إلى ذلك أنَّه باستخدام وحدة التخزين على جانب العميل، يمكن للمستخدم قراءة البيانات.

تخزين الجلسة المشفرة

ملاحظة: يوفر ريلز العديد من آليات التخزين لجداول Hash لجلسة العمل. الأكثر أهمية هو ActionDispatch::Session::CookieStor.

يحفظ CookieStore جدول Hash للجلسة مباشرة في ملف تعريف الارتباط من جانب العميل. يسترد الخادم الجدول Hash لجلسة العمل من ملف تعريف الارتباط ويلغي الحاجة إلى معرِّف جلسة العمل. سيزيد ذلك من سرعة التطبيق بشكل كبير، لكنه خيار تخزين مثير للجدل وعليك التفكير في الآثار الأمنية وقيود التخزين الخاصة به:

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

يستخدم CookieStore مخزن ملف تعريف الارتباط المشفر (encrypted cookie jar) لتوفير موقع آمن ومشفر لتخزين بيانات الجلسات. وبالتالي، توفر الجلسات المستندة إلى ملفات تعريف الارتباط كلًّا من الأمان والسرية لمحتوياتها. يُشتق مفتاح التشفير، بالإضافة إلى مفتاح التحقق المستخدم لملفات تعريف الارتباط الموقعة، من قيمة الضبط secret_key_base.

بدءًا من الإصدار 5.2 من ريلز، تحمى ملفات تعريف الارتباط والجلسات المشفرة باستخدام تشفير AES GCM. هذا النوع من التشفير هو نوع من التشفير والاستيثاق الزوجي والتشفير في خطوة واحدة في حين تنتج أيضا نصوصًا أقصر مقارنة مع الخوارزميات الأخرى المستخدمة سابقا. يُشتق مفتاح ملفات تعريف الارتباط المشفرة مع AES GCM باستخدام قيمة زائدة محددة بواسطة القيمة config.action_dispatch.authenticated_encrypted_cookie_salt.

قبل هذا الإصدار، تُأمَّن ملفات تعريف الارتباط المشفرة باستخدام AES في الوضع CBC مع HMAC باستخدام SHA1 للاستيثاق. اشتقت مفاتيح هذا النوع من التشفير والتحقق من HMAC من خلال القيم الزائدة التي حددها config.action_dispatch.encrypted_cookie_salt و config.action_dispatch.encrypted_signed_cookie_salt على التوالي.

قبل الإصدار 4 من ريلز في كلا الإصدارين 2 و 3، كانت تُحمَى ملفات تعريف الارتباط الخاصة بالجلسات باستخدام التحقق من HMAC فقط. على هذا النحو، لم توفر ملفات تعريف الارتباط الخاصة بهذه الجلسة سوى سلامة المحتوى الخاص بها لأن بيانات الجلسة الفعلية خُزنت في نص عادي مشفر باعتباره base64. هذه هي الطريقة التي تعمل بها ملفات تعريف الارتباط في الإصدار الحالي من ريلز. لا تزال هذه الأنواع من ملفات تعريف الارتباط مفيدة لحماية سلامة بعض البيانات والمعلومات المخزنة من قبل العميل.

لا تستخدم كلمة سر تافهً لـ secret_key_base، أي كلمة من القاموس، أو ذات حروف أقل من 30 حرفًا! بدلًا من ذلك، استخدم rails secret لتوليد مفاتيح سرية!

من المهم أيضًا استخدام قيم زائدة مختلفة لملفات تعريف الارتباط المشفرة والموقعة. قد يؤدي استخدام نفس القيمة لقيم ضبط القيمة الزائدة (salt configuration values) المختلفة إلى نفس المفتاح المشتق المستخدم لميزات أمان مختلفة؛ وهذا قد يؤدي بدوره إلى إضعاف قوة المفتاح.

في تطبيقات الاختبار والتطوير، احصل على secret_key_base مشتق من اسم التطبيق. يجب أن تستخدم البيئات الأخرى مفتاحًا عشوائيًا موجودًا في config/credentials.yml.enc، كما هو موضح هنا في حالة فك تشفيرها:

secret_key_base: 492f...

إذا تلقيت طلبًا عرض فيه كلمة السر (على سبيل المثال أحد التطبيقات التي تمت مشاركة مصدرها)، ففكر بشدة في تغيير كلمة السر.

تدوير إعدادات ملفات تعريف الارتباط المشفرة والموقعة

يُعد التدوير (Rotation) مثاليًا لتغيير ضبط ملفات تعريف الارتباط وضمان عدم صلاحية ملفات تعريف الارتباط القديمة على الفور. عندئذٍ، ستتاح الفرصة للمستخدمين لديك لزيارة موقعك، وقراءة ملفات تعريف الارتباط الخاصة بهم مع تهيئة قديمة وإعادة كتابتها مع التغيير الجديد. يمكن بعد ذلك إزالة التدوير بعد أن تكون مطمئنًّا بما يكفي من امتلاك المستخدمين الفرصة لتحديث ملفات تعريف الارتباط الخاصة بهم.

من الممكن تدوير الأصفار والخدمات المستخدمة لملفات تعريف الارتباط المشفرة والموقعة.

على سبيل المثال، لتغيير القيمة المشفرة المختصرة (digest) المستخدمة لملفات تعريف الارتباط المشفرة الموقعة من SHA1 إلى SHA256، يجب أولًا تعيين قيمة الضبط الجديدة:

Rails.application.config.action_dispatch.signed_cookie_digest = "SHA256"

أضف الآن تدويرًا للقيمة المشفرة عبر SHA1 المختصرة القديمة بحيث تُحدث ملفات تعريف الارتباط الحالية بسلاسة إلى القيمة المشفرة عبر SHA256 المختصرة الجديدة.

Rails.application.config.action_dispatch.cookies_rotations.tap do |cookies|
  cookies.rotate :signed, digest: "SHA1"
end

ثم ستُحسَب القيمة المشفرة المختصرة لأي ملفات تعريف الارتباط المكتوبة باستخدام SHA256. لا يزال من الممكن قراءة ملفات تعريف الارتباط القديمة التي كُتبت باستخدام SHA1، وإذا جرى الوصول إليها آنذاك، سيعاد كتابتها مع القيمة المشفرة المختصرة الجديد بحيث يجري ترقيتها ولن تكون غير صالحة عند إزالة التدوير.

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

على الرغم من أنه يمكنك إعداد العديد من عمليات التدوير على الوجه الذي تريد، فمن غير المعتاد إجراء العديد من التدويرات في وقت واحد.

لمزيد من التفاصيل حول تدوير المفاتيح مع الرسائل المشفرة والموقعة بالإضافة إلى الخيارات المختلفة التي يقبلها التابع rotate، يرجى الرجوع إلى توثيق واجهة برمجة تطبيقات MessageEncryptor و MessageVerifier.

هجمات الإعادة على جلسات CookieStore

ملاحظة: نوع آخر من الهجوم عليك أن تكون على دراية به عند استخدام CookieStore هو هجوم الإعادة (replay attack).

تُنفَّذ هذه الهجمات بالشكل التالي:

  • يتلقى المستخدم كمية مبلغ المال، ثم يخزن المبلغ في جلسة (وهي فكرة سيئة على أي حال، لكننا سنفعل ذلك لأغراض العرض التوضيحي).
  • يشتري المستخدم شيئًا.
  • تخزين قيمة المبلغ المعدلة الجديدة في الجلسة.
  • يأخذ المستخدم ملف تعريف الارتباط من الخطوة الأولى (الذي نسخوه مسبقًا) ويستبدل ملف تعريف الارتباط الحالي في المتصفح.
  • يمتلك المستخدم رصيده الأصلي مرة أخرى.

تضمين رقم خاص (nonce، وهو قيمة عشوائية) في الجلسة يقي من هجمات الإعادة. يكون الرقم الخاص صالحًا مرة واحدة فقط، ويتعين على الخادم تتبع جميع الأرقام الخاصة الصالحة. يصبح الأمر أكثر تعقيدًا إذا كان لديك عدة خوادم للتطبيق. من شأن تخزين الأرقام الخاصة في جدول قاعدة بيانات أن يهزم الهدف الكامل لـ CookieStore (تجنب الوصول إلى قاعدة البيانات).

أفضل حل لذلك هو عدم تخزين هذا النوع من البيانات في الجلسة، ولكن في قاعدة البيانات. في هذه الحالة، خزن الرصيد في قاعدة البيانات و login_in_user_id في الجلسة.

تثبيت الجلسة

ملاحظة: بصرف النظر عن سرقة معرف جلسة المستخدم، قد يُصلِح المهاجم معرف جلسة يعرفه ويجبر الضحية على استعماله، وهذا ما يسمى "تثبيت الجلسة" (Session Fixation).

[[ملف:session_fixation_Rails.png|بديل=خطوات تثبيت جلسة ذات معرف معلوم من طرف المهاجم وتوضيح كيفية خداع المستخدم لاستعمال معرف الجلسة ذاك وإنجاز الاستيثاق للمهاجم.|تصغير|خطوات تثبيت جلسة ذات معرف معلوم من طرف المهاجم وتوضيح كيفية خداع المستخدم لاستعمال معرف الجلسة ذاك وإنجاز الاستيثاق للمهاجم.]]

يركز هذا الهجوم على إصلاح معرِّف جلسة المستخدم المعروف للمهاجم، وإجبار متصفح المستخدم على استخدام هذا المعرف. لذلك، ليس من الضروري أن يسرق المهاجم معرف الجلسة بعد ذلك. إليك كيف يعمل هذا الهجوم:

  • يُنشئ المهاجم معرف جلسة صالح: يُحمِّل صفحة تسجيل الدخول الخاصة بتطبيق الويب حيث يريد إصلاح جلسة العمل، ثم يأخذ معرف جلسة العمل الموجود في ملف تعريف الارتباط من الاستجابة (راجع الرقمين 1 و 2 في الصورة).
  • يحتفظ المهاجم بالجلسة عن طريق الوصول إلى تطبيق الويب بشكل دوري من أجل منع انتهاء صلاحية الجلسة وإبقائها على قيد الحياة.
  • يفرض المهاجم على متصفح المستخدم استخدام معرف جلسة العمل هذا (راجع رقم 3 في الصورة). نظرًا لأنه لا يجوز لك تغيير ملف تعريف ارتباط لنطاق آخر (بسبب نفس سياسة الأصل)، يجب على المهاجم تشغيل JavaScript من مجال تطبيق الويب المستهدف. ينفَّذ هذا الهجوم عبر حقن شيفرة JavaScript في التطبيق بواسطة XSS. إليك مثال على ذلك:
<script>document.cookie="_session_id=16d5b78abb28e3d6206b60f22a03c8d9";</script>

سنتطرق إلى الهجوم XSS والحقن في وقت لاحق.

  • يغري المهاجم الضحية إلى الصفحة المصابة بشيفرة JavaScript. من خلال عرض الصفحة، سيغير متصفح الضحية معرف الجلسة إلى معرف الجلسة الملغوم الذي يمثِّل الفخ.
  • لمَّا كان معرف الجلسة الملغوم الجديد غير مستخدم بعد، فسيطلب تطبيق الويب من المستخدم إجراء استيثاق.
  • من الآن فصاعدا، سيتشارك الضحية والمهاجم استخدام تطبيق الويب مع الجلسة نفسها، إذ أصبحت الجلسة صالحة ولم يلاحظ الضحية الهجوم الذي حصل.

تثبيت الجلسة - التدابير الوقائية

تنبيه: سطر واحد من التعليمات البرمجية سوف يحميك من هجوم تثبيت الجلسة.

إن الإجراء المضاد الأكثر فاعلية هو إصدار معرف جلسة عمل جديد وإعلان أن الرقم القديم غير صالح بعد تسجيل الدخول بنجاح. بهذه الطريقة، لا يمكن للمهاجم استخدام معرف جلسة العمل الثابتة. هذا هو مضاد جيد ضد اختطاف الجلسة أيضًا. فيما يلي كيفية إنشاء جلسة جديدة في ريلز:

reset_session

إذا كنت تستخدم الجوهرة Devise الشائعة لإدارة المستخدمين، فستنتهي الجلسات تلقائيًا عند تسجيل الدخول وتسجيل الخروج نيابة عنك. إذا قمت بالتدوير الخاص بك، تذكر أن تنهي صلاحية الجلسة بعد تسجيل الدخول (عند إنشاء الجلسة). سيؤدي هذا إلى إزالة القيم من الجلسة، وبالتالي يتعين عليك نقلها إلى الجلسة الجديدة.

ومن التدابير المضادة الأخرى حفظ الخصائص الخاصة بمستخدم محدد في الجلسة، والتحقق منها في كل مرة يأتي فيها طلب، ورفض الوصول إذا كانت المعلومات غير متطابقة. يمكن أن تكون هذه الخصائص هي عنوان IP البعيد أو وكيل المستخدم (اسم مستعرض ويب)، على الرغم من أن الأخير غير مرتبط بمستخدم محدَّد بشدة. عند حفظ عنوان IP، يجب أن تضع في حسبانك أن هناك مزودي خدمة إنترنت أو مؤسسات كبيرة تضع مستخدميها خلف الوكلاء (proxies). قد تتغير هذه الخصائص على مدار الجلسة، لذلك لن يتمكن هؤلاء المستخدمون من استخدام التطبيق الخاص بك، أو سيستخدموه ولكن بشكل محدود فقط.

انتهاء الجلسة

ملاحظة: توسع الجلسات التي لا تنتهي صلاحيتها إطلاقًا الإطار الزمني لاحتمالية حدوث عدَّة هجمات مثل التزوير عبر الموقع (CSRF) واختطاف الجلسة وتثبيت الجلسة.

أحد الاحتمالات هو تعيين الطابع الزمني لإنتهاء صلاحية ملف تعريف الارتباط مع معرف جلسة العمل. ومع ذلك، يمكن للعميل تحرير ملفات تعريف الارتباط التي تخزن في متصفح الويب بحيث تصبح الجلسات المنتهية على الخادم أكثر أمانًا. فيما يلي مثال حول كيفية انهاء صلاحية الجلسات في جدول قاعدة البيانات. استدعي ("Session.sweep ("20 minutes لإنهاء الجلسات التي استُخدمت منذ أكثر من 20 دقيقة.

class Session < ApplicationRecord
  def self.sweep(time = 1.hour)
    if time.is_a?(String)
      time = time.split.inject { |count, unit| count.to_i.send(unit) }
    end
 
    delete_all "updated_at < '#{time.ago.to_s(:db)}'"
  end
end

قدم القسم السابق الذي يشرح "تثبيت الجلسة" مشكلة الحفاظ على الجلسات. يمكن للمهاجم الذي يحافظ على جلسة تنتهي كل خمس دقائق أن يبقى الجلسة حية إلى الأبد، على الرغم من أنك قد انتهيت من الجلسات. سيكون الحل البسيط لهذا هو إضافة العمود created_at إلى جدول الجلسات. الآن يمكنك حذف الجلسات التي أُنشئت منذ وقت طويل. استخدم هذا الخط في التابع sweep أعلاه:

delete_all "updated_at < '#{time.ago.to_s(:db)}' OR
  created_at < '#{2.days.ago.to_s(:db)}'"

التزوير عبر الموقع (CSRF)

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

في الفصل الدراسي، تعلمت أن معظم تطبيقات ريلز تستخدم جلسات تستند إلى ملفات تعريف الارتباط. إما أن تخزن معرف جلسة العمل في ملف تعريف الارتباط وأن تحتوي على تجزئة جلسة من جانب الخادم، أو أن تجزئة الجلسة بأكملها تكون على جانب العميل. في كلتا الحالتين، سيرسل المتصفح تلقائيًا ملف تعريف الارتباط على كل طلب إلى نطاق، إذا تمكن من العثور على ملف تعريف ارتباط لهذا النطاق. تكمن النقطة المثيرة للجدل في أنه إذا جاء الطلب من موقع لنطاق مختلف، سيرسل أيضًا ملف تعريف الارتباط. لنبدأ بمثال:

  • يتصفح بوب لوحة الرسائل ويعرض مشاركة من أحد المتسللين حيث يوجد عنصر صورة HTML مهيأ. يشير العنصر إلى أمر في تطبيق إدارة مشروع Bob، بدلاً من ملف صورة:

<img src = "http://www.webapp.com/project/1/destroy">

  • لا تزال جلسة بوب على www.webapp.com على قيد الحياة، لأنه لم يقم بتسجيل الخروج قبل بضع دقائق.
  • من خلال عرض المشاركة، يجد المتصفح علامة صورة. يحاول تحميل الصورة المشتبه بها من www.webapp.com. كما أوضحنا من قبل، يرسل أيضًا على طول ملف تعريف الارتباط بمعرف الجلسة الصحيح.
  • يتحقق تطبيق الويب على www.webapp.com من معلومات المستخدم في تجزئة الجلسة المقابلة ويدمر المشروع بالمعرف 1. ثم يرجع صفحة نتائج غير متوقعة للذاكرة، لذا لن يعرض الصورة.
  • بوب لا يلاحظ الهجوم - ولكن بعد بضعة أيام اكتشف أن المشروع رقم واحد قد اختفى.

من المهم ملاحظة أن الصورة أو الوصلة الفعلية لا يجب وضعها بالضرورة في نطاق تطبيق الويب، يمكن أن تكون في أي مكان - في منتدى أو مشاركة مدونة أو بريد إلكتروني.

يبدو CSRF نادرا جدا في CVE (نقاط الضعف والمشاكل الشائعة) - أقل من 0.1 ٪ في عام 2006 - ولكنه في الحقيقة "عملاق نائم" [غروسمان]. هذا في تناقض صارخ مع النتائج في العديد من أعمال المقاولات الأمنية - تعد CSRF مشكلة أمنية مهمة.

إجراءات CSRF

ملاحظة: أولاً، كما هو مطلوب من قبل W3C، استخدم GET و POST بشكل مناسب. ثانيًا، سيحمي رمز الأمان في طلبات غير GET تطبيقك من CSRF.

يوفر بروتوكول HTTP أساسًا نوعين رئيسيين من الطلبات - GET و POST (يجب استخدام DELETE و PUT و PATCH مثل POST). يوفر World Wide Web Consortium)W3C) قائمة تحقق لاختيار HTTP GET أو POST:

استخدم GET إذا:

  • يكون التفاعل أشبه بسؤال (بمعنى أنه عملية آمنة مثل الاستعلام أو قراءة العملية أو البحث).

استخدم POST إذا:

  • التفاعل أشبه بأمر، أو
  • يغير التفاعل حالة المورد بطريقة يتصورها المستخدم (على سبيل المثال، اشتراك في خدمة)، أو
  • يُحمل المستخدم للمساءلة عن نتائج التفاعل.

إذا كان تطبيق الويب الخاص بك هو RESTful، فقد يستخدم لأفعال HTTP إضافية، مثل PATCH أو PUT أو DELETE. ولكن بعض متصفحات الويب القديمة لا تدعمها - فقط GET و POST. يستخدم ريلز حقل _method مخفي لمعالجة هذه الحالات.

يمكن إرسال طلبات POST تلقائيًا أيضًا. في هذا المثال، يظهر الارتباط www.harmless.com كوجهة في شريط الحالة للمتصفح. ولكنها في الواقع أنشأت بشكل ديناميكي نموذجًا جديدًا يرسل طلب POST.

<a href="<nowiki>http://www.harmless.com/</nowiki>" onclick="  var f = document.createElement('form');  f.style.display = 'none';  this.parentNode.appendChild(f);  f.method = 'POST';  f.action = '<nowiki>http://www.example.com/account/destroy'</nowiki>;  f.submit();  return false;">To the harmless survey</a>

أو يضع المهاجم الرمز في معالج الأحداث onmouseover الخاص بالصورة:

<img src="http://www.harmless.com/img" width="400" height="400" onmouseover="..." />

هناك العديد من الاحتمالات الأخرى، مثل استخدام علامة <script> لتقديم طلب عبر الموقع إلى عنوان URL باستخدام استجابة JSONP أو JavaScript. الاستجابة هي تعليمات برمجية قابلة للتنفيذ يمكن للمهاجم العثور على طريقة للتشغيل، ربما استخراج البيانات الحساسة. للحماية من تسرب البيانات هذا، يجب علينا منع علامات <script> عبر المواقع. ومع ذلك، فإن طلبات Ajax تلتزم بسياسة المتصفح نفسها (فقط يُسمح لموقعك ببدء XmlHttpRequest) حتى نتمكن من السماح لهم بإرجاع استجابات JavaScript بأمان.

ملاحظة: لا يمكننا تمييز أصل العلامة <script> — سواء كانت علامة على موقعك الخاص أو على موقع ضار آخر — لذا يجب علينا حظر جميع <script> عبر اللوحة، حتى إذا كان في الأصل أصلًا آمنًا النصي خدم من موقعك الخاص. في هذه الحالات، تخطي حماية CSRF بشكل صريح من الإجراءات التي تخدم جافا سكريبت الموجهة لعلامة <script>.

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

protect_from_forgery with: :exception

سيتضمن ذلك تلقائيًا رمزًا للأمان في جميع النماذج وطلبات Ajax التي أُنشئت بواسطة ريلز. إذا كان الرمز المميز للأمان لا يطابق ما كان متوقعًا، يطرح استثناء.

ملاحظة: بشكل افتراضي، يتضمن ريلز محولًا للبرمجة غير مزعجة، يضيف رأسًا يسمى X-CSRF-Token مع رمز الأمان على كل مكالمة GET Ajax غير. بدون هذا العنوان، لن تقبل طلبات غير GET Ajax بواسطة ريلز. عند استخدام مكتبة أخرى لإجراء مكالمات Ajax، من الضروري إضافة رمز الأمان كعنوان افتراضي لمكالمات Ajax في مكتبتك. للحصول على الرمز، ألقِ نظرة على العلامة <meta name = 'csrf-token' content = 'THE-TOKEN'> المطبوعة بواسطة <٪ = csrf_meta_tags٪> في عرض التطبيق الخاص بك.

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

rescue_from ActionController::InvalidAuthenticityToken do |exception|

 sign_out_user # Example method that will destroy the user cookies

End

يمكن وضع التابع أعلاه في ApplicationController وسيستدعى عندما يكون رمز CSRF غير موجود أو غير صحيح على طلب غير GET.

لاحظ أن الثغرات الأمنية في البرامج النصية للمواقع المشتركة (XSS) تتجاوز جميع إجراءات حماية CSRF. يتيح XSS للمهاجم الوصول إلى جميع العناصر على الصفحة، حتى يتمكن من قراءة رمز الأمان CSRF من نموذج أو إرسال النموذج مباشرةً. اقرأ المزيد عن XSS لاحقًا.

إعادة التوجيه والملفات

هناك فئة أخرى من الثغرات الأمنية تحيط باستخدام إعادة التوجيه والملفات في تطبيقات الويب.

إعادة التوجيه

ملاحظة: إعادة التوجيه في تطبيق الويب هو أداة للتكسير أقل من قيمتها: لا يمكن للمهاجم توجيه المستخدم إلى موقع فخ فقط، بل قد يؤدي أيضًا إلى إنشاء هجوم قائم بذاته.

عندما يُسمح للمستخدم بتمرير (أجزاء) عنوان URL لإعادة التوجيه، فمن المحتمل أن يكون عرضة للخطر. قد يكون الهجوم الأكثر وضوحًا هو إعادة توجيه المستخدمين إلى تطبيق ويب مزيف يبدو تمامًا كالأصل الأصلي. هذا الهجوم المزيف يسمى التصيد الاحتيالي يعمل عن طريق إرسال رابط غير مريب في رسالة بريد إلكتروني إلى المستخدمين، عن طريق إدخال رابط XSS في تطبيق الويب أو وضع الرابط في موقع خارجي. إنه غير مثير للشك، لأن الرابط يبدأ بعنوان URL إلى تطبيق الويب ويخفي عنوان URL للموقع الخبيث في معامل إعادة التوجيه: http://www.example.com/site/redirect؟to=www.attacker.com . في ما يلي مثال على إجراء قديم:

def legacy

 redirect_to(params.update(action:'main'))

End

سيؤدي هذا إلى إعادة توجيه المستخدم إلى الإجراء الرئيسي إذا حاول الوصول إلى إجراء قديم. كان الهدف هو الحفاظ على معاملات عنوان URL للإجراء القديم وتمريرها إلى الإجراء الرئيسي. ومع ذلك، يمكن استغلالها من قِبل المهاجم إذا تضمنت مفتاح مضيف في عنوان URL:

http://www.example.com/site/legacy?param1=xy&param2=23&host=www.attacker.com

إذا كان في النهاية عنوان URL، فلن يكون من الممكن ملاحظته ويعيد توجيه المستخدم إلى مضيف attacker.com. سيكون الإجراء المضاد البسيط هو تضمين المعاملات المتوقعة فقط في الإجراء القديم (مرة أخرى نهج القائمة البيضاء، بدلاً من إزالة المعاملات غير المتوقعة). وإذا أعدت التوجيه إلى عنوان URL، فتحقق من ذلك باستخدام قائمة بيضاء أو تعبير عادي.

Self-contained XSS

هناك عملية إعادة توجيه أخرى تعتمد على XSS وتعمل في Firefox و Opera باستخدام بروتوكول البيانات. يعرض هذا البروتوكول محتوياته مباشرة في المستعرض ويمكن أن يكون أي شيء من HTML أو JavaScript إلى صور بأكملها:

data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K

هذا المثال عبارة عن JavaScript ترميز Base64 يعرض مربع رسالة بسيط. في عنوان URL لإعادة التوجيه، يمكن للمهاجم إعادة التوجيه إلى عنوان URL هذا باستخدام التعليمة البرمجية الضارة فيه. كإجراء مضاد، لا تسمح للمستخدم بتزويد (أجزاء) عنوان URL المراد إعادة توجيهه إليه.