هل سمعت يومًا بثغرة تُسمّى Blind IDOR؟ تبدو غريبة، أليس كذلك؟
سأتحدث اليوم – بمشيئة الله – عن ثغرة صادفتُها في إحدى أكبر الشركات.
ثغرة بدأت كميزة عادية تمامًا، لا يظهر عليها أي مؤشر يدلّ على خطورتها، ولا حتى ما يستحق التوقّف عنده… لكن مع التجربة والتعمّق تحوّلت إلى واحدة من أغرب وأقوى الثغرات التي مرّت عليّ في هذا المجال.
جهّز قهوتك ولنبدأ…
البداية: فحص اعتيادي للتارغت
كالعادة، بدأت بفحص الهدف الرئيسي:
http://redacted.com
كان الموقع كبيرًا نسبيًا، يحوي الكثير من الصفحات والوظائف والخصائص.
عزمت على فحصه كاملًا، وبدأت أتعمّق فيه يوميًا صفحةً صفحةً، ووظيفةً وظيفةً، مجرّبًا كل ما يمكن… وما لا يمكن.
ومع كثرة المحاولات لم أجد شيئًا قابلًا للاستغلال إطلاقًا، حتى أدوات الـ fuzzing لم تُظهر أي نتيجة مفيدة.
ولكن أثناء مرحلة الـ Recon لفت نظري أمر مهم للغاية…
كل شيء يدور حول API واحد
لاحظت أن المنصّة كلّها تعتمد على API واحد، وكل التفاعل الحقيقي يتم عبر نطاق فرعي محدد:
http://api.redacted.com
ومهما فعلت على الواجهة الأمامية، فالتنفيذ كلّه يمرّ من هنا.
فقررت التركيز عليه بالكامل.
بدأت بإجراء fuzzing موسّع، وكانت النتائج واضحة:
200 → الـ endpoint يعمل
404 → غير موجود
403 → موجود لكن ينقصك التفويض
وكما هو متوقّع، كانت معظم النقاط الحسّاسة تُرجع 403.
جرّبت عشرات طرق الـ bypass:
- تعديل الهيدرز
- تغيير شكل الأحرف
- Encoding & Double Encoding
ولا واحدة نجحت.
وهنا تأكدت أن المشكلة ليست WAF… بل صلاحيات.
اختلاف الصلاحيات بين الحسابات
المنصة تمتلك نوعين من الحسابات:
- حساب أفراد
- حساب شركات
أنشأت حساب شركة، حصلت على الـ token، وعدت لأتلاعب بالـ endpoints التي كانت تُرجِع 403.
وفعلًا…
بعض الـ endpoints الحسّاسة أصبحت مفتوحة فورًا!
بدأت الصورة تتضح:
اختلاف الأدوار هو المفتاح.
البداية الحقيقية: Search Endpoint
من بين النقاط التي ظهرت أثناء الفحص:
/api/v2/all-users/search
الرد كان يعرض قائمة مستخدمين بمعلومات بسيطة جدًا: الاسم – المستخدم – رقم الهوية.
لا شيء مشجّع.
لكنّي معتاد على فحص كل شيء… فبدأت بعمل parameter fuzzing.
فحص البراميترات
وجدت مجموعة براميترات مثل:
page – length – sort – search – username … إلخ.
جميعها كانت طبيعية باستثناء براميتر واحد:
search
بدأت أختبره بقيم مختلفة:
- username → يظهر الحساب
- display name → يظهر الحساب
ثم جربت شيئًا لا ينبغي أن يُفحص أصلًا:
كتبت أوّل جزء من بريدي الإلكتروني: ahmedsdp
والنتيجة؟
عاد لي الردّ يحتوي على حسابي!
مع أن هذا الجزء من البريد لا يظهر إطلاقًا لأي مستخدم.
وهنا أدركت أن البحث لا يعتمد على البيانات الظاهرة…
بل يبحث داخل النموذج الكامل في الباكند.
الربط بين البحث وتحديث الحساب
لاحظت أن صفحة update profile تُرجع نفس هيكلة JSON التي رأيتها في search endpoint.
- نفس الحقول.
- نفس الأسماء.
- نفس النموذج.
وهذا يعني أن البحث يستخدم نموذج بيانات الحساب ذاته.
لكن توجد مشكلة:
لا يمكن تخمين بيانات حسّاسة مباشرة مثل البريد ورقم الهاتف، لا تعرف طولها ولا بدايتها ولا نطاقها… وأي إزعاج للـ WAF سيغضب عليك 😅.
هنا يبدأ التفكير الحقيقي كـ Bug Hunter.
اكتشاف دعم الـ Regex داخل البحث
أثناء تحليل ملفات الـ JS لاحظت أن البحث يستخدم Regex داخليًا.
فقلت لِمَ لا أجرب؟
- ahmed → يظهر
- ahm ed → لا يظهر
- ahm_ed → يظهر!
وهنا تكمن الزبدة…
الرمز _ يُعامل كـ Wildcard لحرف واحد.
ماذا يعني هذا؟ يعني أنك تستطيع تخمين أي قيمة حرفًا حرفًا بطريقة شرطية (نعم/لا)،
تمامًا مثل Blind SQL Injection ولكن على API.
طريقة الاستغلال
الآلية كانت كالتالي:
- تثبيت username للمستخدم عبر براميتر username
- استخدام Regex في search:
إن ظهر الحساب → التخمين صحيح
وإن اختفى → التخمين خاطئ
وبهذا يصبح البحث Oracle يخبرك صح أو خطأ.
بدأت استخراج البريد:
تحديد مزود الخدمة:
@gmail.com
@outlook.com
تحديد عدد الأحرف:
_@gmail.com
__@gmail.com
___@gmail.com
تخمين كل حرف:
a___@gmail.com
b___@gmail.com
… حتى يكتمل البريد كاملًا.
ونفس الشيء للرقم والعنوان وغيرها.
الأتمتة
كتبت سكربت Python يقوم بالعملية تلقائيًا:
تُدخل اسم المستخدم → وفي دقيقة أو دقيقتين تحصل على كل بياناته:
- البريد
- رقم الهاتف
- العنوان
أي معلومة أخرى غير ظاهرة أصلًا
وهنا لم تعد ثغرة IDOR عادية… بل أصبحت Blind IDOR شديدة الخطورة.
محاكاة لما يحدث في الباكند
(تختصر الفكرة هنا: البحث يستخدم Regex ويُعامل _ كـ wildcard، مما يسمح بتخمين قيم حسّاسة من النموذج الداخلي.)
الخلاصة
بدأ الفحص بطريقة اعتيادية جدًا…
لكن بربط السلوك بين الـ endpoints وبتحليل الآلية الداخلية، اتضح أن ميزة البحث مرتبطة بنموذج بيانات الحساب، مما فتح بابًا لاستعلام غير مقصود سمح باستخراج معلومات حسّاسة عبر Blind IDOR.
تم الإبلاغ عن الثغرة وتم إصلاحها بالكامل ولله الحمد.
أهم درس هنا
أغلب الثغرات لا تأتي من خطوة واضحة، بل من ملاحظة صغيرة تربطها بأخرى… حتى تتكوّن لديك الصورة الكاملة.
التحدّي
صنعت لكم تحديًا بسيطًا لمحاكاة ثغرة Blind IDOR باستخدام Flask.
يعتمد على استغلال الـ Regex و الـ Wildcard للحصول على بيانات مخفية.
هدفك: استخراج الفلاق
Flag{......................................}
رابط التحدي:
ننتظر الـ First Blood 🩸👀
شكرًا لقراءتكم… ونلتقي في رايت أب جديد بإذن الله 🫡