شرح سؤال بعد الظهر 1 من امتحان أخصائي أمن المعلومات المسجَّل ربيع 2024 (رييوا 6) ── JWT alg=none وتفويض API والتخفيف المؤقّت بـ WAF

· · أخصائي أمن المعلومات المسجَّل, أخصائي أمن مسجَّل, API, أمن API, JWT, المصادقة, التفويض, WAF, Log4Shell, أمن المعلومات, ثغرة أمنية, IPA

«نتحقّق من توقيع JWT، لذا يمكن الوثوق بمعرّف المستخدم.»

هذا القول نصف صحيح فقط.

السؤال 1 من جلسة بعد الظهر (PM) لامتحان أخصائي أمن المعلومات المسجَّل ربيع 2024 (رييوا 6) مبني حول واجهة برمجة يستدعيها تطبيق هاتف ذكي.1 عند نجاح المصادقة يُصدَر JWT، ويُرفَق ذلك الـ JWT باستدعاءات واجهة البرمجة التي تجلب معلومات المستخدم وتحدّثها. للوهلة الأولى، هذا إعداد عادي تماماً.

غير أنّ التشخيص يكشف المسائل الأربع التالية.

  1. تغيير alg في ترويسة JWT إلى none يمرّر JWT بلا توقيع.
  2. الإبقاء على JWT صالح مع تغيير mid إلى معرّف مستخدم آخر يتيح قراءة معلومات شخص آخر أو تحديثها.
  3. إضافة status=paid غير موثَّق يحوّل مستخدماً من الشريحة المجّانيّة إلى مستخدم مدفوع.
  4. رمز المصادقة الرباعي الأرقام الذي يصل بالبريد يمكن كسره بالقوّة الغاشمة بلا حدّ على المحاولات.

الأربعة تبدو «ثغرات مجاورة للمصادقة»، لكن الأسباب ليست واحدة. ما يُكسَر حدود منفصلة: سلامة الرمز، والتفويض على مستوى الكائن، والتفويض على مستوى الخاصيّة، وتقييد معدّل المحاولات.

النصف الثاني من السؤال يضيف موضوعاً آخر. تُكشَف ثغرة حرجة في مكتبة مفتوحة المصدر واسعة الاستخدام، تتيح لمهاجم تنفيذ شيفرة عن بُعد بإساءة استخدام JNDI Lookup. لا يوجد بعد إصلاح ولا قاعدة WAF مكتملة. في الأثناء، يسأل السؤال كيف تؤكّد الأثر، وأين ينبغي أن ينظر WAF، ولماذا ينبغي أن يكون وضع WAF الأوّلي «كشف» لا «حظر».

يستند هذا المقال إلى الإجابات النموذجيّة الرسميّة2 وتعليق التصحيح3، ويمرّ ليس فقط بإجابة كلّ سؤال بل لماذا تلك هي الإجابة، وإلى أيّ حدّ ينبغي أن تصمّم بصرامة أكبر في الممارسة.

نظرة عامّة على السؤاليبيّن حدّ الثقة المكسور في كلّ مرحلة - رمز المصادقة، JWT، تفويض API، وثغرة المكتبةبلا حدّ محاولاتيسمح بـ alg=noneيثق بـ midstatus=paidJNDI/LDAP/HTTPتطبيق المستخدمرمز مصادقة رباعيإصدار JWTواجهة مستخدمإخراج السجلّمكتبة ضعيفةتنفيذ شيفرة عن بُعدقراءة/تحديث بيانات مستخدم آخرتغيير حالة الفوترة

الشكل 1: نظرة عامّة على السؤال. يُكسَر حدّ ثقة مختلف في كلّ مرحلة.

1. الخلاصة أوّلاً

  • خاصيّة واجهة برمجة RESTful بعدم الاحتفاظ بحالة جلسة تُدعى انعدام الحالة (stateless). هذا لا يعني أنّ الخادم لا يملك قاعدة بيانات ولا حالة مستخدم على الإطلاق
  • رمز مصادقة رباعي الأرقام له 10,000 قيمة ممكنة. عند 10 محاولات في الثانية، ينجح المهاجم بعد متوسّط 5,000 محاولة، أي 500 ثانية ── أقصر من مدّة الصلاحيّة 10 دقائق، لذا لا يوقفه الانتهاء وحده
  • الحدّ الأدنى من الإجراءات ضدّ alg=none هو التأكّد من أنّ alg في ترويسة JWT ليس NONE. لكن في الممارسة ينبغي تثبيت مجموعة الخوارزميّات المسموحة على جانب الخادم
  • حتّى مع JWT صالح، يجب ألّا يُوثَق بـ mid الطلب. إمّا طابق معرّف المستخدم داخل JWT مع mid، أو ── بأمان أكبر ── لا تقبل mid من العميل أصلاً وحدّد الهدف من JWT
  • إضافة status=paid مشكلة Mass Assignment، حيث تُربَط خصائص خارج المواصفة مباشرةً بالكائن الداخلي. استخدم DTO التحديث قائمةَ سماح، ولا تدع المستخدم يغيّر حالة الفوترة أبداً
  • الإجابة النموذجيّة لإجراء القوّة الغاشمة هي منطق يقفل الحساب متى تجاوز عدد الإخفاقات المتتالية عتبة. في الممارسة، أضف تأخيرات متدرّجة وضوابط حسب المصدر أيضاً
  • لتأكيد أثر ثغرة حرجة كُشِفت حديثاً، بدل إصدار أمر مدمِّر، سجِّل الوصولات إلى index.html لخادم اختبار لتأكيد أنّ تنفيذ الشيفرة عن بُعد يصل فعلاً
  • لأنّ سلسلة الهجوم تُحمَل في ترويسة HTTP، هدف فحص WAF هو Header. كتعبير نمطي يعالج تبديل حالة الأحرف، استخدم شيئاً مثل \W[jJ][nN][dD][iI]\W
  • فائدة بدء WAF بوضع «كشف» أنّه يمنع حظر حركة الأعمال المشروعة بإنذار كاذب. عندما يصل تنبيه، افحص ما إذا كان هجوماً حقيقيّاً، ثم انتقل إلى وضع الحظر بعد ضبط القاعدة
  • WAF إجراء مؤقّت فقط؛ الإصلاح الجذري هو تحديث المكتبة المتأثّرة إلى نسخة مرقَّعة

2. كيف يقابل السيناريو الأسئلة

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

ورقة السؤال تجرِّد أسماء المنتجات والخدمات المعيّنة. كذلك لا يعيد هذا المقال إنتاج رسوم IPA ولا نصّها، بل يعيد صياغة البنية اللازمة لفهم الأسئلة فقط.

السؤال الموضوع فصل هذا المقال
السؤال 1 طبيعة واجهات برمجة RESTful الفصل 4
السؤال 2(1) زمن كسر الرمز الرباعي بالقوّة الغاشمة الفصل 5
السؤال 2(2) JWT alg=none الفصل 6
السؤال 2(3) الوصول إلى مستخدم آخر عبر mid الفصل 7
السؤال 2(4) الخلل الذي يقبل status خارج المواصفة الفصل 8
السؤال 2(5) إجراءات القوّة الغاشمة الفصل 9
السؤال 3(1) تأكيد وجود ثغرة بأمان الفصل 11
السؤال 3(2)(3) أين ينظر WAF، والتعبير النمطي الفصل 12
السؤال 3(4) فائدة وضع الكشف وكيف يُشغَّل الفصل 13

يشير تعليق التصحيح إلى أنّ معدّل الإجابة الصحيحة الإجمالي كان نحو المتوسّط. غير أنّه يشير أيضاً إلى أنّ معدّل الإجابة الصحيحة كان أدنى بعض الشيء لإجراء العبث بـ JWT في السؤال 2(2) وللآليّة اللازمة على خادم التحقّق في السؤال 3(1). لا يمكن الإجابة عن أيّهما من المفردات وحدها. عليك تتبّع أيّ قيمة غيّرها المهاجم، وأيّ معالجة تدفّقت إليها، وأين انتهى بها الأمر موثوقاً بها.

3. هذا ليس «مشكلة مصادقة» واحدة فحسب

ترتيب السؤال كلّه حسب حدّ الثقة يعطي التالي.

[معرّف المستخدم / كلمة المرور]
          |
          v
[فحص الرمز الرباعي] ---- بلا حدّ محاولات ----> قوّة غاشمة
          |
          v
[إصدار JWT]
          |
          v
[مكتبة JWT] ------- تسمح بـ alg=none ------> العبث بمعرّف المستخدم
          |
          v
[واجهة المستخدم]
    |             |
    |             +-- تمرّر status جملةً ----> خلل تفويض على مستوى الخاصيّة
    |
    +-- تثق بـ mid -----------------------> خلل تفويض على مستوى الكائن

[تسجيل إدخال خارجي]
          |
          v
[مكتبة ضعيفة] ---- JNDI/LDAP/HTTP ------> تنفيذ شيفرة عن بُعد

أهمّ تمييز هنا هو التالي.

الفحص السؤال الذي يطرحه مثال مكسور في هذا السيناريو
المصادقة من أنت كسر الرمز الرباعي بالقوّة الغاشمة
التحقّق من الرمز هل عُبِث بمعلومات الهويّة تلك alg=none
التفويض على مستوى الكائن أيجوز لهذا المستخدم الوصول إلى بيانات هذا المستخدم تبديل mid
التفويض على مستوى الخاصيّة أيجوز تغيير هذا الحقل status=paid
حدّ الإدخال إلى التنفيذ هل يُفسَّر الإدخال الخارجي أمراً JNDI Lookup

نجاح فحص واحد ليس أبداً سبباً لتجاوز الفحص التالي. مستخدم ذو JWT صالح ليس بالضرورة مسموحاً له بقراءة بيانات شخص آخر. مستخدم مسموح له بتحديث بياناته ليس بالضرورة مسموحاً له بتغيير حالة فوترته أيضاً.

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

الفرق بين المصادقة والتفويضالمصادقة تؤكّد الذات، والتفويض يؤكّد ما يُسمَح لتلك الذات بفعلهالمصادقةمن أنتالتفويضما يجوز لك فعله

الشكل 2: الفرق بين المصادقة والتفويض. المصادقة تأتي أوّلاً؛ التفويض فحص منفصل.

4. السؤال 1 ── ماذا يعني «انعدام الحالة»

يسأل السؤال 1 عن أحد مبادئ تصميم واجهات برمجة RESTful: خاصيّة عدم إجراء إدارة جلسة.

الإجابة هي انعدام الحالة (stateless).

انعدام الحالة يعني أنّ الخادم لا يحتاج إلى تذكّر حالة المحادثة للطلب السابق، لأنّ كلّ طلب بمفرده يحمل كلّ ما يلزم لمعالجته. في هذا السؤال، يُرفق تطبيق الهاتف الذكي JWT بترويسة Authorization في كلّ طلب. يتحقّق الخادم من ذلك الـ JWT ويحدّد مستخدم ذلك الطلب منه.

قراءة شائعة خاطئة هي أخذ «انعدام الحالة» على أنّه «الخادم لا يملك أيّ حالة على الإطلاق». في الواقع، يملك عادةً الحالة التالية.

  • قاعدة البيانات التي تخزّن معلومات المستخدم وبيانات الصحّة
  • حالة الفوترة
  • قيمة رمز المصادقة وانتهاء صلاحيّته وعدّاد إخفاقه
  • مفتاح توقيع JWT
  • معلومات الإلغاء، للتصاميم التي تستخدم قائمة إلغاء
  • السجلّات وسجلّات التدقيق

ما لا يملكه هو حالة جلسة على جانب الخادم توجد صرفاً لمواصلة محادثة، كشرط مسبق تعتمد عليه كلّ استدعاء لواجهة البرمجة.

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

5. السؤال 2(1) ── رمز رباعي يُكسَر في متوسّط 500 ثانية

ترسل واجهة مصادقة رقماً رباعي الأرقام بالبريد متى تطابق معرّف المستخدم وكلمة المرور. ثم تصدر JWT متى تطابق معرّف المستخدم والرمز الرباعي. الرمز صالح 10 دقائق من التوليد.

في التشخيص، كانت 10 محاولات في الثانية ممكنة. يسأل السؤال كم ثانية يستغرق، في المتوسّط، الاختراق.

الحساب هو «نصف فضاء المرشّحين»

رقم رباعي الأرقام، بما فيه صفر بادئ، له الاحتمالات العشرة آلاف التالية.

0000, 0001, 0002, ... , 9999

إن اختير الجواب الصحيح عشوائيّاً بتوزيع منتظم، يصل مهاجم يجرّب المرشّحين بالترتيب بلا تكرار إلى الصحيح، في المتوسّط، بعد نصف فضاء المرشّحين.

متوسّط عدد المحاولات = 10,000 / 2 = 5,000
متوسّط الزمن                = 5,000 / 10 محاولات في الثانية = 500 ثانية

لذا الفراغ b هو 500.

أسوأ حالة تستغرق حتى 1,000 ثانية، لكن السؤال يطلب المتوسّط. ومدّة صلاحيّة الرمز 600 ثانية ── أطول من متوسّط زمن الكسر 500 ثانية. لذلك يُحكَم بأنّه «مرجَّح أن يُكسَر».

حسّ المقياس لرمز المصادقة الرباعيتجربة 10,000 مرشّح بمعدّل 10 في الثانية تتوسّط 5,000 محاولة و500 ثانية، وهي أقلّ من مدّة الصلاحيّة 600 ثانيةمتوسّط 10,000 / 2 = 5,000 محاولة500 ثانية أقلّ من 600 ثانية10,000 مرشّحمتوسّط زمن الكسر 500 ثانيةمدّة الصلاحيّة 600 ثانيةيمكن كسره ضمن مدّة الصلاحيّة

الشكل 9: حسّ المقياس لرمز المصادقة الرباعي الأرقام. تجربة نصف فضاء المرشّحين في المتوسّط تكسره ضمن مدّة الصلاحيّة.

تقصير زمن الانتهاء وحده يخسر إن كان فضاء المرشّحين صغيراً

قوّة رمز المصادقة لا تُحدَّد بعدد الأرقام وحده ولا بمدّة الصلاحيّة وحدها.

عدد المحاولات الممكنة خلال مدّة الصلاحيّة
= محاولات في الثانية × مدّة الصلاحيّة
= 10 × 600
= 6,000 محاولة

بتجربة قيم غير مكرَّرة بالترتيب، يستطيع مهاجم فحص 60% من الاحتمالات العشرة آلاف ضمن مدّة الصلاحيّة. تعيين زمن انتهاء ليس كافياً بمفرده إن لم يُحدَّ عدد المحاولات.

يتطلّب NIST SP 800-63B الحالي ستّة أرقام على الأقلّ للأسرار قصيرة الأجل المستخدمة في المصادقة خارج النطاق، ويفرض حدّاً لمعدّل المحاولات متى كان للسرّ أقلّ من 64 بت من الإنتروبي. ويدعو أيضاً إلى عدم استخدام البريد للمصادقة خارج النطاق.4 إجابة الامتحان تعمل ضمن المواصفة المعطاة لرمز رباعي يُرسَل بالبريد، لكن لتصميم جديد في الممارسة، ينبغي إعادة النظر في تلك المقدّمة نفسها.

6. السؤال 2(2) ── alg=none مشكلة «ترك المهاجم يختار طريقة التحقّق»

يتكوّن JWT في هذا السؤال من ثلاثة أجزاء: ترويسة، وحمولة، وتوقيع.

base64url(header).base64url(payload).base64url(signature)

سجّلت الترويسة RS256 خوارزميّة مستخدمة للتوقيع. تحتوي الحمولة معرّف المستخدم ووقت الإصدار وانتهاء الصلاحيّة.

غيّر الفاحص الشيئين التاليين.

  1. تغيير alg الترويسة من RS256 إلى NONE.
  2. تغيير معرّف المستخدم في الحمولة إلى مستخدم مختلف.

بإرسال ذلك الـ JWT، نجح التحقّق وأتاح للفاحص انتحال شخص آخر.

تدفّق هجوم JWT alg=noneتغيير alg إلى none في JWT صالح وإعادة كتابة معرّف المستخدم يمرّر الطلبتغيير alg الترويسة إلى noneيتخطّى التحقّق من التوقيعJWT صالحalg=RS256user=user01JWT مُعبث بهalg=noneuser=user02الخادم يقبلهبوصفه user02

الشكل 3: تدفّق هجوم JWT alg=none. المهاجم يختار خوارزميّة التحقّق.

none ليست خطأ إملائيّاً

يعرّف RFC 7519 «Unsecured JWT» ── JWT بلا توقيع ولا تشفير، وalg فيه none.5 لذا قيمة none ليست شيئاً لا يوجد ببساطة في المواصفة.

المشكلة أنّ واجهة برمجة كان ينبغي أن تقبل JWT موقَّعة فقط قبلت none التي حدّدها المهاجم.

مكتوبة مفاهيميّاً، تبدو المعالجة الضعيفة هكذا.

1. اقرأ ترويسة JWT.
2. انظر إلى alg المكتوب في الترويسة، واختر طريقة التحقّق.
3. إن كان alg هو none، فلا تتحقّق من التوقيع.
4. ثق بمعرّف المستخدم في الحمولة.

قوّة الأمان نفسها تُختار من إدخال يتحكّم فيه المهاجم.

إجابة الامتحان

يسأل السؤال، في 20 حرفاً أو أقلّ لكلّ منهما، أيّ بيانات ينبغي أن تتحقّق منها المكتبة Q بعد الإصلاح، وماذا ينبغي أن يفحص ذلك التحقّق.

الإجابة النموذجيّة كالتالي.

البند جوهر الإجابة
البيانات المراد التحقّق منها القيمة المحدَّدة في alg ترويسة JWT
ماذا يُتحقَّق أنّها ليست NONE

كإصلاح مباشر للثغرة الموصوفة في السؤال، هذا صحيح.

في الممارسة، لا تكتفِ بـ «أيّ شيء سوى NONE»

هنا نحتاج إلى فصل إجابة الامتحان عن التوصية العمليّة.

ينصّ RFC 8725 على أنّ مكتبة JWT ينبغي أن تتيح للمستدعي تحديد مجموعة خوارزميّات مسموحة، وألّا يُستخدَم شيء خارج تلك المجموعة.6 بعبارة أخرى، الفكرة هي هذه.

نهج سيّئ:
  اقبل إن كان token.header.alg != "none"

نهج جيّد:
  اقبل فقط إن كان ضمن serverConfig.allowedAlgorithms
  مثال: allowedAlgorithms = ["RS256"]

رفض none وحده قد يترك خوارزميّات ضعيفة أخرى، أو إمكان خلط خوارزميّات حيث تُخطَأ خطّة مفتاح عامّ على أنّها مفتاح متناظر. المبدأ هو ألّا تواصل إضافة شروط سلبيّة لما تقبل، بل تثبّت مجموعة ضيّقة إيجابيّة لما يُسمَح به.

ينبغي أن يؤكّد التحقّق من JWT ليس الخوارزميّة فحسب بل، بحسب حالة الاستخدام، على الأقلّ التالي أيضاً.

البند ما تؤكّده
التوقيع هل يمكن التحقّق منه بالمفتاح والخوارزميّة المتوقَّعين
iss هل هو مُصدِر موثوق
aud هل صدر الرمز لهذه الواجهة
exp هل هو ضمن مدّة صلاحيّته
nbf هل ليس قبل وقت «غير صالح قبل»
sub أو معرّف المستخدم هل هو ذات صالحة ضمن التطبيق
نوع الرمز هل يُخلَط رمز هويّة برمز وصول، إلخ

في هذا السؤال اسم مفتاح الحمولة هو user، لكن في الممارسة ينبغي إمّا استخدام sub القياسي أو تعريف معنى ادّعاء مخصّص بوضوح.

التحقّق الآمن مقابل غير الآمن من JWTالتحقّق غير الآمن يعتمد على alg، والآمن يستخدم قائمة سماح على جانب الخادمتحقّق آمنخوارزميّات مسموحة مضبوطة على الخادممثال: RS256أكِّد أنّ alg ترويسة JWTضمن قائمة السماحتحقّق من التوقيع وiss وaud وexpتحقّق غير آمناقرأ alg من ترويسة JWTاقبل إن كان alg هو none

الشكل 4: التحقّق الآمن مقابل غير الآمن. في الممارسة، ثبِّت مجموعة ضيّقة من الخوارزميّات المسموحة.

Base64url ليس تشفيراً

هناك سوء فهم شائع آخر حول JWT. الترويسة والحمولة ممثَّلتان بـ base64url، لكن ذلك ليس تشفيراً. أيّ شخص يستطيع فكّ الترميز وقراءتهما.

ما يضمنه التوقيع، وفقط عندما يتحقّق صحيحاً، هو أنّ المحتوى لم يُعبَث به منذ الإصدار. لا يعني أنّ معلومات شخصيّة تريد إبقاؤها سرّيّة يجوز وضعها في حمولة JWT موقَّع.

7. السؤال 2(3) ── حتّى مع JWT صالح، تغيير mid قرأ بيانات شخص آخر

التالي هجوم لا يعبث بـ JWT نفسه.

تتلقّى واجهة المستخدم معرّف مستخدم يُدعى mid على GET أو PUT. تجلب الوحدة المشتركة P أو تحدّث، في قاعدة البيانات، معلومات المستخدم المرتبطة بذلك الـ mid.

بنية الهجوم بسيطة.

معرّف المستخدم داخل JWT: user01    <- JWT موقَّع صحيحاً
mid الطلب:          user02   <- غيّره المهاجم

توقيع JWT صالح، لذا تنجح المصادقة. لكن الواجهة تثق بـ mid=user02 كما هو، وتعيد معلومات user02.

هذه حالة نموذجيّة لما تدعوه OWASP API Security Top 10 2023 Broken Object Level Authorization (BOLA). كلّما وُصِل إلى بيانات باستخدام معرّف كائن حدّده المستخدم، يجب فحص التفويض لذلك الكائن بعينه في كلّ مرّة.7

هجوم BOLAاستخدام JWT صالح مع تغيير mid الطلب إلى معرّف مستخدم مختلفJWT user01mid user02يثق بـ midمهاجمواجهة المستخدميعيد بيانات user02 من قاعدة البيانات

الشكل 5: هجوم BOLA. تمرّ المصادقة، لكن التفويض لم يُفحَص قط.

إجابة السؤال

التسطير 2 في الجدول 5 يطلب، في 40 حرفاً أو أقلّ، المعالجة المراد إضافتها إلى الاستدعاء إلى الوحدة المشتركة P.

الإجابة النموذجيّة:

منطق يتحقّق ممّا إذا كان معرّف المستخدم الموجود في JWT يطابق قيمة mid

فائدة التحقّق داخل الوحدة المشتركة P أنّ فحص التفويض نفسه يسهل تطبيقه على GET وPUT معاً، وعلى أيّ واجهة مستقبليّة تستخدم P أيضاً. نسخ المقارنة نفسها إلى كلّ شاشة أو نقطة نهاية على حدة يعني أنّها ستغيب في مكان ما.

تصميم أكثر أماناً هو عدم قبول mid أصلاً

لواجهة برمجة تجلب أو تحدّث معلومات المستدعي نفسه فقط، لا حاجة لقبول معرّف مستخدم من العميل أصلاً.

GET /users/me
Authorization: Bearer <JWT>

على جانب الخادم، تُستخرَج الذات من JWT بعد التحقّق.

principal = validateJwt(request.authorization)
userId = principal.subject
return repository.getUser(userId)

الأمر نفسه ينطبق على التحديثات.

principal = validateJwt(request.authorization)
input = validateProfileUpdate(request.body)
repository.updateProfile(
    userId = principal.subject,
    name = input.name,
    age = input.age
)

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

إن احتاج مسؤول إلى العمل على معلومات مستخدم آخر، فافصل كما يلي.

PUT /users/me                  للمستخدمين العامّين
PUT /admin/users/{userId}      للمسؤولين

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

كيف تمنع BOLAبدل استخدام mid الطلب، قرّر الهدف أو افحصه من موضوع JWTGET /users/me + JWTخذ sub من JWTمطابقةلا مطابقةبلا midمستخدمواجهة برمجةإن وُجد midفهل يطابق subأعد بياناتكرفض 403بحث في قاعدة البيانات بـ JWT sub

الشكل 6: كيف تمنع BOLA. إمّا لا تقبل mid، أو افحصه مقابل موضوع JWT.

تمييز المصادقة عن التفويض في جملة واحدة

في الامتحان وفي الممارسة، تساعد الصياغة التالية.

  • المصادقة: من أنت
  • التفويض: ماذا يجوز لذلك الشخص فعله

نجاح التحقّق من توقيع JWT يوصلك فقط إلى «يمكن الوثوق بالذات التي يمثّلها هذا الرمز». ما إذا كانت «تلك الذات يجوز لها قراءة user02» يجب تأكيده على حدة.

8. السؤال 2(4) ── status=paid خلل تفويض على مستوى الخاصيّة

تعرّف مواصفة واجهة المستخدم التالي معاملات تحديث.

mid   معرّف المستخدم
name  الاسم
age   العمر

غير أنّ الفاحص أضاف القيمة التالية، وهي ليست في المواصفة.

status=paid

ثم تغيّرت حالة مستخدم الشريحة المجّانيّة إلى حالة مستخدم دافع.

بحسب السؤال، لم تتحقّق الخدمة L من المعاملات التي تلقّتها؛ مرّرتها كلّها مباشرةً إلى الوحدة المشتركة P، التي بُنيت بحيث تستطيع تحديث قاعدة البيانات مباشرةً.

إجابة الفراغ c هي الوحدة المشتركة P.

Mass Assignmentيُضاف status=paid خارج المواصفة ويُطبَّق جملةً على الكائن الداخلييضيف المهاجم status=paidربط تلقائيحُفظ في قاعدة البياناتمواصفة APImid / name / ageجسم الطلبالوحدة المشتركة Pحالة الفوترة تغيّرت إلى paid

الشكل 7: Mass Assignment. خاصيّة خارج المواصفة تُطبَّق جملةً على الكائن الداخلي.

الفرق عن BOLA

تبديل mid من الفصل السابق وإضافة status هذه تبدوان متشابهتين، لكن دقّة ما يُحمى تختلف.

الثغرة ما يغيّره المهاجم ما ينبغي فحصه فعلاً
تبديل mid الكائن المستهدف أيجوز لهذا المستخدم الوصول إلى سجلّ هذا المستخدم
إضافة status خاصيّة داخل الكائن أيجوز لهذا المستخدم تغيير هذا الحقل

تعامل OWASP API Security Top 10 2023 الأخيرة على أنّها Broken Object Property Level Authorization، طاوِيةً ما كان يُدعى Mass Assignment في هذا التصنيف.8

«وضع JSON مباشرةً في الكيان» خطر

التنفيذ الضعيف، مفاهيميّاً، يبدو هكذا.

entity = repository.find(body.mid)
bindAllProperties(entity, body)
repository.save(entity)

حتّى إن كان للشاشة حقول إدخال لـ name وage فقط، يستطيع مهاجم صياغة طلب HTTP مباشرةً. غياب حقل من الواجهة ليس حدّ أمان.

تنفيذ آمن يجعل الحقول القابلة للتحديث صريحة.

input = parseExactSchema(body, fields = ["name", "age"])

entity = repository.find(authenticatedUserId)
entity.name = input.name
entity.age  = input.age
repository.save(entity)

أمران مهمّان هنا.

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

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

التفويض على مستوى الخاصيّةيحمل DTO التحديث قائمة سماح فقط، وتُرفَض الخصائص المجهولةتحقّق المخطّطنعملامسار مخصّصDTO التحديث - قائمة سماحnameageجسم الطلبالحقول المسموحةفقط موجودةحدّث name/age للكيانأرجع خطأخدمة الدفعإشعار مُتحقَّقحدّث status=paid

الشكل 8: التفويض على مستوى الخاصيّة. قيّد الحقول القابلة للتحديث بقائمة سماح، وغيّر حالة الفوترة فقط عبر مسار منفصل.

ينبغي أن تتغيّر status فقط من نتيجة الدفع

status=paid ليست جزءاً من ملفّ المستخدم. إنّها حالة مشتقّة من حقيقة على جانب الخادم: أنّ الدفع نجح.

تحديث ملفّ المستخدم
  -> يمكن تغيير name / age فقط

إشعار مُتحقَّق من خدمة الدفع
  -> طابق paymentId
  -> امنع المعالجة المكرَّرة
  -> غيّر status إلى paid

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

9. السؤال 2(5) ── إجراءات القوّة الغاشمة تحتفظ بعدّاد الإخفاق حالةً

لكسر الرمز الرباعي بالقوّة الغاشمة، يسأل الفراغ d في الجدول 5، في 30 حرفاً أو أقلّ، عن المعالجة التي تنتمي هناك. العتبة 10.

الإجابة النموذجيّة:

منطق يقفل الحساب متى تجاوز عدد الإخفاقات المتتالية العتبة

هذا لا يناقض انعدام الحالة من السؤال 1. عدم الاحتفاظ بحالة محادثة استدعاء واجهة جلسةَ خادم، وإدامة عدّاد الإخفاق اللازم لقرار أمني، شيئان مختلفان.

مع حدّ معدّل المحاولات ودونهبلا حدّ يُكسَر الرمز في متوسّط 500 ثانية، لكن حدّ عدّاد الإخفاق يبطئ الهجوم بحدّةمع حدّتنهار سرعة الهجومالحساب مقفولقفل بعد 10 إخفاقاتتأخير متدرّجبلا حدّنحو 500 ثانيةتنجح المصادقة10 محاولات في الثانية

الشكل 10: مع حدّ معدّل المحاولات ودونه. حدّ عدّاد الإخفاق يستطيع عمليّاً إيقاف القوّة الغاشمة.

في الممارسة، لا تعتمد على القفل الدائم وحده

حدّ محاولات لكلّ حساب ضروري، لكن إن عرف مهاجم معرّف مستخدم شخص آخر، يستطيع الإخفاق 10 مرّات عمداً لإقفال المستخدم الشرعي. في الممارسة إذن اجمع التالي.

الضبط الدور
عدّاد إخفاق لكلّ حساب يوقف القوّة الغاشمة ضدّ حساب واحد
أوقات انتظار متدرّجة تتسامح مع أخطاء إدخال المستخدم الشرعي بينما تبطئ الهجوم
ضوابط حسب عنوان IP المصدر والجهاز وASN وغيرها تكبح هجمات تجرّب مرّات قليلة ضدّ حسابات كثيرة
قرارات قائمة على المخاطر تطبّق قيوداً أقوى لمناطق أو أجهزة أو سرعات غير معتادة
إشعار المستخدم يدع المستخدم يلاحظ هجوماً أو خطأه هو
إجراء استعادة آمن يمنع أن يصبح قناة إلغاء القفل نفسها مسار هجوم

علاوة على ذلك، عند إعادة إرسال رمز، يجب ألّا يُعاد عدّاد الإخفاق إلى الصفر ── وإلّا استطاع مهاجم تجديد ميزانيّة محاولاته كلّما استدعى واجهة إعادة الإرسال. يطلب NIST SP 800-63B الحالي كذلك ألّا يُعاد تعيين عدّاد الإخفاق حتّى عند توليد سرّ مصادقة جديد.4

اجعل رمز المصادقة لمرّة واحدة

يركّز السؤال على زمن الانتهاء، لكن في الممارسة يلزم أيضاً التالي.

  • أبطل رمزاً ناجحاً فوراً.
  • ارفض إعادة استخدام الرمز نفسه.
  • لا تترك الرمز نفسه في السجلّات.
  • اجعل الاستجابة بحيث لا يمكن استخدام نجاح فحص الرمز أو فشله للاستدلال على وجود مستخدم.
  • ضع حدّ محاولات على واجهة إرسال الرمز أيضاً.

ما دام سرّ قصير يُستخدَم، لا يمكن ترك الأمان للتوليد العشوائي وحده.

إجراءات رمز المصادقةإلى جانب عدد الأرقام والانتهاء، احمِ بحدود المحاولات ورفض إعادة الاستخدام والإشعار وغيرهارمز المصادقةزِد عدد الأرقامقصِّر الانتهاءحدّ معدّل المحاولاتأبطل بعد النجاحلا تُعِد عدّاد الإخفاق عند إعادة الإرساللا تترك الرمز في السجلّاتضبط حسب المصدر

الشكل 11: إجراءات رمز المصادقة. اجمع عدد الأرقام والانتهاء مع ضبط المحاولات والممارسات التشغيليّة.

10. تمييز أجزاء السؤال 2 الأربعة في صفحة واحدة

النقاط في السؤال 2 السهلة الخلط، منظَّمة حسب القيمة التي تحكّم فيها المهاجم.

الهجوم القيمة التي غيّرها المهاجم ما كان ينبغي ألّا يُوثَق به الإصلاح الجذري
العبث بـ JWT alg ترويسة JWT، ومعرّف المستخدم في الحمولة خوارزميّة التحقّق التي يعلنها الرمز نفسه ثبِّت الخوارزميّات المسموحة على جانب الخادم
قراءة معلومات مستخدم آخر mid الطلب معرّف الهدف الذي حدّده العميل طابقه مع موضوع JWT، أو حدّد معرّف الهدف من JWT
الترقية إلى مستخدم مدفوع status خارج المواصفة كلّ الخصائص المربوطة تلقائيّاً اجعل الخصائص القابلة للتحديث قائمة سماح
كسر الرمز الرباعي مرشّحو otp محاولات مصادقة بلا حدّ أضف حدود معدّل المحاولات وتأخيرات وقرارات مخاطر

يهمّ ألّا تُجمَع كلّ هذا تحت «تحقّق من الإدخال».

  • alg سياسة تشفيريّة.
  • mid تفويض على مستوى الكائن.
  • status تفويض على مستوى الخاصيّة.
  • otp مقاومة للتخمين عبر الإنترنت.

حتّى ضمن طلب HTTP نفسه، سبب وجوب حماية كلّ واحد مختلف.

11. السؤال 3(1) ── تأكيد تنفيذ شيفرة عن بُعد دون إحداث ضرر

بعد إطلاق الخدمة، تُكشَف ثغرة حرجة V في المكتبة H، مكتبة مفتوحة المصدر واسعة الاستخدام. تسلسل أحداث السؤال كالتالي.

  1. يضع المهاجم سلسلة تحتوي JNDI Lookup في ترويسة HTTP ويرسلها.
  2. يسجّل الخادم المستهدف تلك القيمة.
  3. تقيّم المكتبة الضعيفة JNDI Lookup وتستعلم خادم LDAP للمهاجم.
  4. يعيد ردّ LDAP عنوان URL لخادم HTTP للمهاجم.
  5. يجلب الخادم المستهدف ملفّ الصنف وينفّذ الأمر.

مع حجب اسم المنتج بعينه، يُقرأ هذا هجوماً من نوع Log4Shell (CVE-2021-44228). وصف Apache نفسه كذلك يصف الثغرة بأنّها إن تحكّم مهاجم برسائل السجلّ أو المعاملات، استطاع تنفيذ شيفرة اعتباطيّة محمَّلة من خادم LDAP.9

تدفّق تأكيد ثغرة من نوع Log4Shellاستخدم استدعاءً راجعاً غير ضارّ لتأكيد ما إذا كانت السلسلة من JNDI إلى تنفيذ شيفرة عن بُعد تمرّ فعلاًحقن حمولة jndi/ldapفي x-api-versionJNDI Lookupردّ عنوان HTTPسجِّل GETأكِّد قابليّة الوصولمهاجمخادم ضعيفمعالجة السجلّخادم LDAP خبيثخادم HTTP خبيثindex.htmlخادم اختبارسجلّ الوصولأُكِّدت الثغرة

الشكل 12: تدفّق تأكيد ثغرة من نوع Log4Shell. تُؤكَّد قابليّة الوصول بتسجيل وصول HTTP لا بإصدار أمر مدمِّر.

شيفرة التحقّق تُطلِق وصول HTTP غير ضارّ فقط

تشغّل الشركة G شيفرة تحقّق لا أثر لها على النظام، لتأكيد ما إذا كان يمكن استغلال الثغرة V من الخارج. الأمر الوحيد الذي تصدره شيفرة التحقّق هو جلب index.html لخادم الاختبار.

يسأل السؤال 3(1) عمّا يلزم تنفيذه على خادم الاختبار لتأكيد أنّ الأمر نُفِّذ.

الإجابة النموذجيّة:

آليّة تسجّل الوصولات إلى index.html لخادم الاختبار وتتيح تأكيدها

إن سجّل سجلّ وصول خادم الويب GETاً من الخادم المستهدف، يؤكّد ذلك، على الأقلّ، أنّ السلسلة التالية مرّت.

طلب HTTP خارجي
  -> معالجة السجلّ
  -> JNDI Lookup
  -> ردّ LDAP
  -> جلب الصنف
  -> تنفيذ أمر التحقّق
  -> وصول HTTP إلى خادم الاختبار

لماذا «عرض نصّ على الشاشة» لا يكفي

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

تسجيل الوصول على جانب خادم الاختبار ينتج دليلاً قابلاً للرصد أنّ الخادم المستهدف وصل فعلاً إلى العالم الخارجي.

عند إجراء هذا النوع من التحقّق في الممارسة، راعِ دائماً التالي.

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

«تأكيد أنّ تنفيذ شيفرة اعتباطيّة ممكن» و«تنفيذ شيفرة خطرة اعتباطيّة» ليسا الشيء نفسه. أبقِ الآثار الجانبيّة عند الحدّ الأدنى اللازم لتحقيق الهدف.

12. السؤال 3(2)(3) ── يفحص WAF ترويسة HTTP

يتيح WAF الخدمة N اختيار GET أو POST أو PUT أو ANY أو Header أو COOKIE أو Multipart هدفاً للفحص.

تدخل شيفرة الهجوم في قيمة ترويسة HTTP تُدعى x-api-version. لذا الفراغات e وf في الجدول 6 كلاهما Header.

قابل الموقع المعطى في النصّ مباشرةً بهدف فحص WAF

هذا أقلّ عن معرفة عامّة وأكثر عن قراءة تدفّق البيانات في نصّ السؤال.

أين وُضعت سلسلة الهجوم:
  ترويسة x-api-version
          |
          v
هدف فحص WAF:
  Header

ليست معامل GET ولا جسم POST. بدل النظر إلى قائمة ميزات WAF واختيار ANY لأنّ «يبدو هجوماً»، أجب بـ الموقع الذي يقول نصّ السؤال إنّ المهاجم وضع القيمة فيه.

معالجة تبديل حالة الأحرف

كان الاقتراح الأوّل، مفاهيميّاً، القاعدة التالية.

Header  \Wjndi\W  حظر
Header  \Wldap\W  حظر

لكن تبديل الحالة، كما في jNdI، يتهرّب من نمط يطابق الأحرف الصغيرة فقط.

الإجابة النموذجيّة للسؤال 3(3) هي أيّ من التالي.

\W[jJ][nN][dD][iI]\W
\W(j|J)(n|N)(d|D)(i|I)\W

في كتيّب السؤال قد يبدو الشرطة المائلة العكسيّة علامة ين في الخطّ الياباني، لكن كتعبير نمطي هي \W. تطابق \W أيّ محرف سوى الأحرف والأرقام والشرطة السفليّة. في صياغة JNDI Lookup، تظهر محارف غير كلميّة مثل ${ و: مباشرةً قبل jndi وبعده، والنمط مكتوب ليلتقط تلك أيضاً.

يمكن تطبيق الفكرة نفسها لجعل جانب ldap غير حسّاس لحالة الأحرف أيضاً.

\W[lL][dD][aA][pP]\W

لا تعامل هذا التعبير النمطي «إجراء Log4Shell مكتملاً»

الامتحان يطلب تعبيراً نمطيّاً يعالج تقنيّة التهرّب المعروضة في نصّ السؤال. هجمات العالم الحقيقي قد تتضمّن تقسيم سلاسل، وLookups بديلة، وترميزاً، وبروتوكولات أخرى، وتنويعات أخرى يصعب تغطيتها بالتواقيع وحدها.

التموضع العملي إذن كالتالي.

  1. احظر مؤقّتاً أنماط الهجوم المعروفة حالياً بـ WAF.
  2. حقّق ما إذا كانت المكتبة المتأثّرة موجودة فعلاً.
  3. قيّد LDAP وRMI وحركة HTTP غير الضروريّة الصادرة.
  4. حدِّث إلى نسخة مرقَّعة.
  5. بعد التحديث، افحص السجلّات أيضاً وحقّق ما إذا وقع اختراق.

WAF طبقة تشتري وقتاً إلى أن تتوفّر نسخة مرقَّعة.

موضع WAFWAF طبقة تخفيف مؤقّتة، والإصلاح الجذري تحديث المكتبة إلى نسخة مرقَّعةقاعدة WAFكشف/حظرقيّد الحركة الصادرةكُشِفت ثغرة حرجةأكِّد الأثرتخفيف مؤقّتأوقف نمط الهجوم مؤقّتاًأغلق مسار الإساءةحدِّث إلى المكتبة المرقَّعةمراجعة لاحقة ومنع

الشكل 13: موضع WAF. WAF يشتري وقتاً فقط إلى أن يصل رقعة؛ الإصلاح الجذري هو التحديث.

13. السؤال 3(4) ── لماذا نبدأ بـ «كشف»

لقاعدة WAF المحدَّثة، ينصح Z، أخصائي أمن مسجَّل، بضبط الوضع على «كشف» لا «حظر» لمدّة ثابتة بعد دخولها الإنتاج.

يسأل السؤال، في 25 حرفاً أو أقلّ لكلّ منهما، عن فائدة استخدام وضع الكشف وعمّا ينبغي فعله لتقليل الضرر.

الإجابة النموذجيّة:

البند جوهر الإجابة
الفائدة يمكن أن يمنع حظراً ناتجاً عن إنذار كاذب
ما يُفعَل افحص ما إذا كان هجوماً كلّما وصل تنبيه

وضع الكشف ليس وضع «لا تفعل شيئاً»

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

في المقابل، يحتاج جانب التشغيل إلى التالي.

وُصل تنبيه
   |
   v
افحص الطلب المعني
   |
   +-- حركة مشروعة -> ضيّق القاعدة، فكِّر في استثناء
   |
   +-- هجوم             -> اعزل الهدف، احفظ السجلّات، حقّق في الأثر، انتقل إلى الحظر

إن لم ينظر أحد إلى التنبيهات، فلا أثر حمائي لوضع الكشف أصلاً. الكشف يعمل فقط مقترناً بعمليّة تشغيليّة تراقب وتحكم.

المسار من الكشف إلى الحظر

إجراء طرح نموذجي كالتالي.

  1. شغِّل وضع الكشف ضدّ حركة حقيقيّة.
  2. صنِّف الإصابات إنذارات كاذبة أو إيجابيّات حقيقيّة.
  3. اضبط الترويسة المستهدفة والمسار والواجهة وحدود الكلمات وما إلى ذلك.
  4. أكِّد أنّ الأثر على الحركة المشروعة مقبول.
  5. انتقل إلى وضع الحظر.
  6. راقب عدد الحظر وأثر الأعمال.

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

من وضع كشف WAF إلى وضع الحظرراقب التنبيهات في وضع الكشف، اضبط الإنذارات الكاذبة، ثم انتقل إلى وضع الحظرحركة حقيقيّةإنذار كاذبهجوموضع الكشفرُفع تنبيههجوم أمإنذار كاذباضبط القاعدةانتقل إلى وضع الحظرراقب عدد الحظر وأثر الأعمال

الشكل 14: من الكشف إلى الحظر. راقب واضبط أوّلاً، أكِّد أنّ الأثر مقبول، ثم انتقل إلى الحظر.

14. WAF إجراء مؤقّت؛ التحديث هو الإصلاح الجذري

في السؤال، لم يكن لموقع المكتبة H الرسمي إصلاح ولا حلّ مؤقّت بعد، وحتّى قاعدة WAF الشاملة لمزوّد السحابة كانت ستستغرق حتى 72 ساعة. لذا تؤكّد الشركة G الأثر بنفسها وتحظر مؤقّتاً على الأقلّ الأنماط التي حدّدتها بالفعل.

هذا التسلسل هو الشكل الأساسي لاستجابة الحوادث.

المرحلة الغرض الاستجابة في هذا السؤال
تأكيد الأثر احكم ما إذا كانت منظّمتك فعلاً في خطر أكِّد قابليّة الاستغلال من الخارج باستدعاء راجع غير ضارّ
تخفيف مؤقّت اشترِ وقتاً إلى أن يصل إصلاح قواعد WAF، كشف/حظر، قيود الحركة الصادرة
إصلاح جذري أزل السبب الضعيف حدِّث إلى مكتبة مرقَّعة
مراجعة لاحقة افحص ما إذا كانت قد استُغِلّت بالفعل حقّق في سجلّات WAF والتطبيق وDNS والوكيل وغيرها
منع التكرار سرِّع القرار التالي جرد الاعتمادات، SBOM، إجراء التحديث، مسار الاتّصال

«لا نعلم إن كنّا نستخدمه» أكبر مصدر تأخير

في السؤال، حتّى عندما تسأل الشركة G الشركة F ما إذا كانت تستخدم المكتبة H، يستغرق الجواب وقتاً لأنّ تحليلاً تفصيليّاً للإعداد يلزم.

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

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

SBOM ليس الهدف بذاته. إنّه فهرس للإجابة، في وقت قصير، عن «أيّ أنظمة قيد التشغيل تؤثّر فيها هذه الثغرة».

لا تتوقّف عن التحقيق متى حدّثت

قد تكون هوجمت بالفعل حول وقت كشف الثغرة. التحديث إلى نسخة مرقَّعة يوقف الاستغلال المستقبلي، لكنّه لا يمحو بيانات اعتماد اختُرقت بالفعل ولا باباً خلفيّاً زُرِع بالفعل.

لثغرة من نوع Log4Shell، حقّق على الأقلّ في الزوايا التالية.

  • طلبات HTTP تحتوي سلاسل مريبة تشير إلى JNDI أو LDAP.
  • اتّصال من خادم التطبيق إلى LDAP أو RMI أو HTTP خارجي.
  • إطلاق عمليّات ابن غير معتادة.
  • إنشاء JAR أو أصناف أو سكربتات أو تنفيذيّات مريبة.
  • الوصول إلى بيانات اعتماد سحابة أو متغيّرات بيئة.
  • المصادقة وتغييرات الصلاحيّات والنقل الصادر حول وقت التحديث.

يهمّ ألّا تستنتج «لم نُهاجَم» من سجلّات WAF وحدها. هناك مسارات داخليّة لا تمرّ بـ WAF قط، وسجلّات لم تُحفَظ في الماضي.

15. طريقة قراءة تسهّل كسب النقاط في الامتحان

هذا السؤال أقلّ اختبار معرفة وأكثر تمريناً في قراءة الفجوة بين المواصفة والتنفيذ.

15.1 افصل «المواصفة» عن «التنفيذ» في الجداول

في مسألة status، تمرّ قيمة غائبة عن مواصفة الواجهة في التنفيذ.

المواصفة:
  mid / name / age

التنفيذ:
  أرسل كلّ المعاملات المستلَمة إلى P

متى رأيت هذه الفجوة، يتّضح أنّ الفراغ c هو الوحدة المشتركة P.

15.2 ارسم خطاً تحت القيمة التي غيّرها المهاجم

القيمة المتغيّرة في كلّ هجوم كالتالي.

  • alg ترويسة JWT
  • معرّف المستخدم في حمولة JWT
  • معامل الواجهة mid
  • status خارج المواصفة
  • otp واجهة المصادقة
  • ترويسة HTTP x-api-version

يكاد كلّ سؤال يسأل «أين ينبغي التحقّق من تلك القيمة».

15.3 أعد الإجابة إلى مصطلحات نصّ السؤال نفسه

في الممارسة تستطيع تسمية هذه «BOLA» و«Mass Assignment» و«rate limiting». لكن ما يطلبه السؤال هو معالجة ملموسة مطابقة لبنية نصّ السؤال.

مثال ضعيف:

نفِّذ التفويض على نحو مناسب.

مثال جيّد:

تحقّق ممّا إذا كان معرّف المستخدم الموجود في JWT يطابق قيمة mid.

مثال ضعيف:

اتّخذ إجراءات ضدّ القوّة الغاشمة.

مثال جيّد:

اقفل الحساب متى تجاوز عدد الإخفاقات المتتالية العتبة.

معرفة الاسم المجرّد وحده لا تنتج إجابة يمكن تصحيحها ضمن حدّ الأحرف.

15.4 لـ WAF، تتبّع «أين وُضِع»

يُقرَّر هدف فحص WAF لا بالتخمين من نوع الهجوم، بل من أين وُضعت سلسلة الهجوم.

وُضع في ترويسة x-api-version
        ↓
هدف الفحص هو Header

ملاحظة تعليق التصحيح أنّ معدّل الإجابة الصحيحة للسؤال 3(1) كان أدنى بعض الشيء أيضاً لأنّ إجابات كثيرة لم تطابق تدفّق الهجوم في الشكل 6. مجرّد إعادة رسم تسلسل الهجوم بأسهم يكشف ما ينبغي رصده.

16. قائمة تحقّق لمراجعات واجهات البرمجة في العالم الحقيقي

قائمة تحقّق لإعادة هذا السؤال إلى تصميم ومراجعات شيفرة فعليّة.

التحقّق من JWT

  • خوارزميّة التوقيع المسموحة ثابتة في إعداد الخادم.
  • تُرفَض none والخوارزميّات غير المتوقَّعة.
  • يُتحقَّق من التوقيع وiss وaud وexp وnbf بحسب حالة الاستخدام.
  • لا تُخلَط رموز الهويّة ورموز الوصول ورموز التجديد بعضها ببعض.
  • هناك إجراء لتدوير المفاتيح والإلغاء.
  • لا تُوضَع معلومات يجب أن تبقى سرّيّة في حمولة JWT.

التفويض على مستوى الكائن

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

التفويض على مستوى الخاصيّة

  • نوع الإدخال الخارجي وكيان قاعدة البيانات منفصلان.
  • الحقول القابلة للتحديث مُعدَّدة قائمةَ سماح.
  • تُرفَض الخصائص خارج المواصفة أو تُدقَّق.
  • حالة مثل الصلاحيّات والفوترة والموافقة والملكيّة لا يمكن تغييرها من إدخال المستخدم.
  • تستبعد الاستجابات أيضاً خصائص سرّيّة غير ضروريّة.

محاولات المصادقة

  • هناك حدّ لعدّاد الإخفاق لكلّ حساب.
  • هناك تأخير متدرّج وضبط حسب المصدر.
  • لا يُعاد تعيين عدّاد الإخفاق عند إعادة إصدار الرمز.
  • يمكن استخدام رمز المصادقة مرّة واحدة فقط.
  • لا تُترَك رموز المصادقة وكلمات المرور في السجلّات.
  • إجراء إلغاء القفل/الاستعادة ليس نفسه مسار مصادقة أضعف.

ثغرات حرجة في المكتبات المعتمدة

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

17. الوجهان للمكوّنات المشتركة، كما يظهران عبر هذا السؤال

يضمّ هذا السؤال مكوّنين مشتركين: مكتبة إدارة JWT Q والوحدة المشتركة P.

للمكوّنات المشتركة فوائد كبرى.

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

من الجهة الأخرى، تنتشر الأخطاء أيضاً عبر النظام كلّه.

  • إن قبلت المكتبة Q alg=none، تصبح كلّ واجهة تستخدم JWT ضعيفة.
  • إن قبلت الوحدة المشتركة P أيّ mid أو status، يصبح GET وPUT كلاهما ضعيفين.
  • إن استُخدِمت المكتبة الضعيفة H في الأساس، يصبح كلّ مسار يسجّل ترويسات HTTP جزءاً من سطح الهجوم.

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

مثلاً، اجعل عقد P كالتالي.

P.getOwnUser(authenticatedSubject)
P.updateOwnProfile(authenticatedSubject, ProfileUpdate{name, age})

أكثر أماناً ألّا تعرض واجهة منخفضة المستوى مثل التالية مباشرةً للمستدعين العاديّين.

P.getUser(arbitraryMid)
P.updateUser(arbitraryMap)

الأخيرة تلزم فقط مجموعة محدودة من المسارات، مثل المعالجة الإداريّة. تسليم تلك الحرّيّة المنخفضة المستوى إلى كلّ واجهة ينتج تصميماً يعتمد على أن يستخدمها كلّ مستدعٍ صحيحاً، في كلّ مرّة.

18. الخلاصة

سؤال بعد الظهر 1 لربيع 2024 (رييوا 6) سؤال يفصل موضوعات أمن واجهات البرمجة واحداً واحداً.

استخدام JWT لا يعني أنّ المصادقة آمنة. ترك المهاجم يختار خوارزميّة التوقيع يتيح إعادة كتابة معرّف المستخدم.

توقيع JWT صالح لا يعني أنّ التفويض صحيح. الوثوق بـ mid الطلب يتيح لمستخدم شرعي الوصول إلى معلومات شخص آخر.

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

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

وضع قاعدة في WAF لا يعني أنّ الثغرة أُصلِحت. الكشف والحظر يشتريان وقتاً فقط؛ تؤكّد الأثر وفي النهاية تحدّث المكتبة.

مقابلة الثغرات بالإجراءاتيقابل كلّ ثغرة بحدّ ثقتها وإجراءهاالتحقّق من الرمزتفويض على مستوى الكائنتفويض على مستوى الخاصيّةضبط محاولات المصادقةمن الإدخال إلى التنفيذالعبث بـ JWTثبِّت الخوارزميّة المسموحةتبديل midطابق موضوع JWT / لا حاجة لـ midstatus=paidاجعل DTO التحديث قائمة سماحقوّة غاشمة على الرمز الرباعيحدّ إخفاق / تأخيرثغرة من نوع Log4Shellتحديث المكتبة / WAF

الشكل 15: مقابلة الثغرات بالإجراءات. افصل الإصلاح حسب أيّ حدّ كُسِر.

مبدأ واحد يجري عبر هذا السؤال كلّه.

لا تجعل نجاح الفحص السابق سبباً لتجاوز حدّ الثقة التالي أبداً.

تغطي المقالات السابقة في هذه السلسلة ثغرة XSS المخزَّنة في سؤال بعد الظهر 1 لخريف 2023 (رييوا 5) وتسريب البيانات عبر شبكة Wi-Fi للزوّار في سؤال بعد الظهر 2 لخريف 2023 (رييوا 5). لنظرة على ما ينبغي فحصه عبر الموقع بأكمله، انظر أيضاً استخدام «كيفية إنشاء موقع ويب آمن» الصادر عن IPA كقائمة تحقّق.

الخلاصة النهائيّةيبيّن أنّ نجاح الفحص السابق ليس أبداً سبباً لتجاوز حدّ الثقة التالينجاح المصادقةالتحقّق من توقيع JWTالتفويض على مستوى الكائنالتفويض على مستوى الخاصيّةحدّ معدّل المحاولاتحدّ الإدخال إلى التنفيذWAF / تحديث المكتبة

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

روابط مرجعيّة

  1. IPA, كتيّب أسئلة بعد الظهر لامتحان أخصائي أمن المعلومات المسجَّل ربيع 2024 (رييوا 6). نصّ السؤال الذي يستند إليه هذا المقال. 

  2. IPA, الإجابات النموذجيّة لبعد الظهر لامتحان أخصائي أمن المعلومات المسجَّل ربيع 2024 (رييوا 6). الإجابة النموذجيّة الرسميّة لكلّ سؤال. 

  3. IPA, تعليق التصحيح لبعد الظهر لامتحان أخصائي أمن المعلومات المسجَّل ربيع 2024 (رييوا 6). شرح لمعدّلات الإجابة الصحيحة والأخطاء الشائعة. 

  4. NIST, SP 800-63B: Authentication and Authenticator Management. يضع أعداد أرقام الأسرار قصيرة الأجل، وحدود معدّل المحاولات، وعدّاد الإخفاق عند إعادة الإصدار، وعدم استخدام البريد للمصادقة خارج النطاق، بين متطلّبات أخرى.  2

  5. RFC Editor, RFC 7519: JSON Web Token (JWT). مواصفة JWT، بما فيها Unsecured JWT وalg=none

  6. RFC Editor, RFC 8725: JSON Web Token Best Current Practices. وثيقة BCP التي تضع تثبيت مجموعة الخوارزميّات المسموحة، والتحقّق من المُصدِر والموضوع والجمهور، بين ممارسات أخرى. 

  7. OWASP, API1:2023 Broken Object Level Authorization. يشرح الحاجة إلى فحص التفويض لكلّ معرّف كائن يحدّده المستخدم. 

  8. OWASP, API3:2023 Broken Object Property Level Authorization. يشرح خلل التفويض على مستوى الخاصيّة، بما فيه Mass Assignment، وإجراءاته. 

  9. Apache Logging Services, Security. يشرح أثر CVE-2021-44228، وتنفيذ الشيفرة عبر JNDI وLDAP، والإصدارات المصلحة. 

أحدث المقالات التي تشترك في نفس الوسوم. عمّق فهمك بمواضيع مرتبطة.

من أين تبدأ الشركات الصغيرة والمتوسطة في تدابير الأمان؟ ── كيفيّة قراءة الإصدار 4.0 من «الدليل الإرشادي لتدابير أمن المعلومات للشركات الصغيرة والمتوسطة» الصادر عن IPA

من أين ينبغي أن تبدأ الشركات الصغيرة والمتوسطة في تدابير الأمان؟ استناداً إلى الإصدار 4.0 من «الدليل الإرشادي لتدابير أمن المعلومات للشرك...

لكي لا تنسى تحديد «كم ثانية يجب أن يستغرق التشغيل حتى يكون مُرضياً» ── تنظيم المتطلبات غير الوظيفية باستخدام «درجة المتطلبات غير الوظيفية» الصادرة عن IPA

كثير من أسباب الخلاف حول «السرعة بطيئة» أو «التعامل مع الأعطال لم يكن متوقَّعاً» يعود إلى نسيان تحديد المتطلبات غير الوظيفية. نشرح للجانب...

كيف يجب صياغة عقود التطوير الخارجي والتشغيل والصيانة ── التمييز بين شبه التفويض والمقاولة كما تُعلِّمه «العقد النموذجي» الصادر عن IPA

عند إسناد تطوير الأنظمة إلى جهة خارجية، كيف ينبغي صياغة العقد؟ اعتماداً على «العقد النموذجي لمعاملات نظم المعلومات» الذي تنشره IPA، نشرح ...

ترتبط هذه المقالة بشكل طبيعي بصفحات الخدمات التالية.

الأسئلة الشائعة

أسئلة شائعة حول موضوع هذه المقالة.

لماذا يستطيع مهاجم انتحال شخص آخر رغم نجاح التحقّق من توقيع JWT؟
في هذا السؤال، قبلت مكتبة إدارة JWT قيمة alg في ترويسة JWT تماماً كما حدّدها المهاجم، وعاملت JWT ذا alg=none على أنّه صالح بلا توقيع أصلاً. لذلك يمرّ التحقّق حتّى بعد إعادة كتابة معرّف المستخدم في الحمولة. إجابة الامتحان هي التحقّق من alg في ترويسة JWT والتأكّد من أنّ قيمته ليست NONE. لكن في الممارسة، رفض NONE وحده لا يكفي. ثبِّت الخوارزميّات المسموح باستخدامها ── مثلاً RS256 ── في إعداد جانب الخادم، حتّى لا تُستخدَم الخوارزميّة التي يعلنها الرمز مباشرةً للاختيار. ينبغي أيضاً التحقّق من المُصدِر والجمهور وانتهاء الصلاحيّة والموضوع وما إلى ذلك، بحسب حالة الاستخدام.
هل مقارنة معرّف المستخدم داخل JWT مع mid الطلب كافية كإجراء تفويض؟
لأغراض إجابة هذا الامتحان، نعم كافية. التحقّق داخل الوحدة المشتركة P من أنّ معرّف المستخدم الموجود في JWT يطابق mid يوقف هجوماً يحدّد mid شخص آخر. لكن لواجهة برمجة لا تعالج إلّا معلومات المستدعي نفسه، يكون أكثر أماناً في الممارسة ألّا تقبل mid من العميل أصلاً، وأن تحدّد معرّف المستخدم من موضوع JWT بعد التحقّق. استخدام شيء مثل GET /users/me أو PUT /users/me يجعل من الأصعب أن يغيب منطق المقارنة ببساطة. واجهة برمجة يدير فيها مسؤول مستخدماً آخر ينبغي فصلها إلى نقطة نهاية مستقلّة بسياسة تفويض خاصّة.
لماذا لا يكفي التحقّق العادي من المدخلات وحده لإيقاف الهجوم الذي يضيف status؟
لأنّك إن تحقّقت من طول name أو مدى age، فذلك لا يفعل شيئاً إذا رُبط status ── حقل ما كان ينبغي قبوله أصلاً ── تلقائيّاً ومُرِّر مباشرةً إلى الكائن الداخلي. المسألة ليست شكل القيمة؛ إنّها تفويض على مستوى الخاصيّة، أي هل يُسمح للمستخدم بتغيير تلك الخاصيّة أصلاً. عرِّف name وage فقط في نوع إدخال التحديث، وارفض الخصائص المجهولة. يجب تغيير حالة الفوترة فقط من أحداث يثق بها الخادم، مثل نتيجة نجاح من خدمة الدفع.
رمز المصادقة الرباعي الأرقام ينتهي بعد 10 دقائق ── فلماذا يبقى خطراً؟
لأنّ المرشّحين من 0000 إلى 9999 عشرة آلاف فقط، وبـ 10 محاولات في الثانية ينجح المهاجم بعد متوسّط 5,000 محاولة ── أي 500 ثانية. مدّة الصلاحيّة 10 دقائق تعادل 600 ثانية، لذا فإنّ تجربة مرشّحين غير مكرَّرين بالترتيب تتيح فحص 6,000 منها ضمن تلك النافذة. زمن الانتهاء وحده لا يوقف الهجوم بالقوّة الغاشمة. فضاء المرشّحين وسرعة المحاولة وسقف عدد المحاولات تحتاج إلى تصميم معاً.
إجراء الامتحان هو قفل الحساب ── فهل القفل الفوري وحده يكفي في الممارسة أيضاً؟
لا. الفراغ في السؤال يطلب منطقاً يقفل الحساب متى تجاوز عدد الإخفاقات المتتالية عتبة، لكن قفلاً ثابتاً دائماً وحده يتيح لمهاجم قفل حساب شخص آخر عمداً كحرمان من الخدمة. في الممارسة، اجمع عدّاد إخفاق لكلّ حساب مع أوقات انتظار متدرّجة، وتقييم مخاطر المصدر والجهاز، وإشعارات، وإجراء استعادة. يهمّ أيضاً ألّا يُعيد إصدار رمز جديد عدّاد الإخفاق إلى الصفر.
ما فائدة ضبط WAF على الكشف لا الحظر؟
تعني أنّ حركة الأعمال المشروعة لا تُوقَف حتّى عندما تُحكَم سلسلة عاديّة خطأً على أنّها هجوم. في الإجابة النموذجيّة، الفائدة أنّه يمكن منع حظر ناتج عن إنذار كاذب، وما ينبغي فعله هو فحص ما إذا كان هجوماً كلّما وصل تنبيه. وضع الكشف ليس إعداداً تتركه وشأنه. يُستخدَم فترة مراقبة تراجع فيها السجلّات وتستبعد الإنذارات الكاذبة وتضبط القاعدة ثم تنتقل إلى الحظر. في طارئ تُستغَل فيه فعلاً ثغرة حرجة معروفة، قد يكون معقولاً موازنة ذلك بمخاطر التوفّر واختيار الحظر من البداية بدلاً من ذلك.
هل المكتبة H في هذا السؤال هي Log4j؟
السؤال يحجب اسم المنتج، لكن تسلسل الهجوم ── JNDI Lookup، وخادم LDAP، وجلب صنف من خادم HTTP، وسلسلة مضمَّنة في ترويسة HTTP، ودرجة أساس CVSS v3.1 عالية ── يُقرأ طبيعيّاً تجريداً لـ CVE-2021-44228 المعروفة باسم Log4Shell. يشرح هذا المقال ذلك التقابل، لكن الامتحان لا يطلب تسمية المنتج بعينه. يمكن الإجابة من إجراء الهجوم المعطى ومواصفة WAF وحدهما.
ماذا ينبغي أن تعيده إلى الممارسة من هذا السؤال؟
أنّ نجاح المصادقة، وكون JWT لم يُعبَث به، والسماح بالوصول إلى الكائن المستهدف، والسماح بتغيير الخاصيّة المستهدفة، كلّها فحوصات منفصلة. فوق ذلك، يحتاج رمز مصادقة قصير حدّاً لمعدّل المحاولات، ولثغرة مكتبة حرجة تُجري تأكيد الأثر والدفاع المؤقّت والإصلاح الجذري على التوازي. الخلاصات العمليّة الجوهريّة: تجميع التفويض في مكوّنات مشتركة، وجعل مخطّط الإدخال قائمة سماح، وتثبيت شروط التحقّق من JWT على جانب الخادم، وتتبع المكتبات المعتمدة حتّى تستطيع تحديثها.

الملف الشخصي للمؤلف

صفحة الملف الشخصي لمؤلف المقالة.

غو كومورا

مؤسّس شركة كومورا سوفت ذ.م.م.

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

العودة إلى المدونة