تحدث هذه الثغرة عندما لا يتحقق الـ API من أن المستخدم الذي يطلب "كائن" معين (Object) لديه الصلاحية للوصول إليه. يعتمد الـ API غالباً على معرف الكائن (ID) الذي يرسله المستخدم في الرابط (URL)، وإذا لم يكن هناك فحص دقيق، يمكن للمستخدم الوصول لبيانات غيره بمجرد تغيير الـ ID.
تخيل أنك ذهبت إلى المطعم 🍔:
-
طلبت وجبتك، وأعطاك الموظف رقم طلب (7) وقال لك: "انتظر حتى يجهز طلبك".
-
أنت جلست على الطاولة، وشفت ورقة صغيرة مكتوب عليها رقم طلبك (7).
-
فجأة، خطرت لك فكرة! مسحت الرقم (7) وكتبت بدلاً منه (8).
-
ذهبت للموظف وقلت له: "أعطني هذا الطلب".
-
الموظف نظر للورقة، ورأى رقم (8)، فذهب وأحضر لك وجبة الشخص الآخر (الذي طلب رقم 8) وأعطاك إياها بدون ما يتأكد من هويتك أو يطلب منك الفاتورة الأصلية!
👉 هذه هي ثغرة BOLA:
-
👨💻 أنت: المخترق (تلاعبت بالـ ID).
-
🌐 المطعم (الموظف): هو الـ API (نفذ الطلب بناءً على الرقم فقط).
-
⚠️ المشكلة: الموظف وثق في "الرقم" الذي أعطيته إياه ولم يتأكد هل أنت فعلاً صاحب الطلب رقم 8 أم لا.
هذا هو النوع الأسهل والأكثر شيوعاً. المعرفات تكون عبارة عن أرقام متسلسلة.
-
المثال:
GET /api/orders/1001← يغيرها الهكر إلى1002. -
🎯 الهدف: سحب بيانات الطلبات لجميع العملاء عبر سكربت بسيط.
🧬 2. التلاعب بالـ UUIDs/GUIDs (The "Hidden" ID)
يعتقد المبرمج أن استخدام UUID (مثل 550e8400-e29b-41d4-a716-446655440000) يحمي من BOLA لأن تخمينه مستحيل.
⚠️ الثغرة: الهكر لا يخمن الـ UUID، بل يبحث عنه في أماكن أخرى (مثل رابط بروفايل المستخدم العام، أو في سجلات الـ API المسربة). بمجرد حصوله على الـ UUID، يجربه في Endpoints حساسة.
أحياناً الـ API يتأكد من صاحب الحساب، لكنه ينسى التأكد من "الأشياء" التابعة للحساب.
- المثال: حسابك (User 5) يطلب عرض فاتورة (Invoice 99). الـ API يتأكد أنك (User 5)، لكنه لا يتأكد أن (Invoice 99) تتبع لك فعلاً!
أخطر أنواع BOLA هو الذي يسمح بتغيير الحالة وليس فقط القراءة.
-
المثال:
-
GET /api/posts/50← مسموح للجميع (رؤية المنشور). -
DELETE /api/posts/50← يجب أن يكون لصاحب المنشور فقط.
-
-
⚠️ الثغرة: إذا لم يفحص الـ API الصلاحية عند استخدامDELETEأوPUT(تعديل)، يمكن لأي شخص حذف منشورات الآخرين.
تكمن خطورة BOLA في أنها تضرب "قلب" المنطق البرمجي، وتفتح أبواباً كان من المفترض أن تظل مغلقة للأبد. إليك الأسباب:
-
🔓 تسريب بيانات ضخم (Massive Data Breach): بما أن الـ APIs مصممة للتعامل مع البيانات الخام (JSON/XML)، فإن ثغرة BOLA واحدة قد تسمح للمخترق بسحب بيانات آلاف أو ملايين المستخدمين (مثل الإيميلات، العناوين، الأرقام السرية، والبيانات البنكية) عبر "سكربت" بسيط يغير الـ IDs بشكل آلي.
-
🕵️ التجسس والخصوصية (Privacy Invasion): تخيل تطبيق محادثات أو تطبيقاً طبياً؛ ثغرة BOLA قد تسمح لشخص ما بقراءة رسائل خاصة أو سجلات طبية لا تخصه بمجرد معرفة "رقم الطلب"، مما يؤدي لكوارث قانونية وفقدان ثقة المستخدمين.
-
🔨 التلاعب بالبيانات (Data Manipulation): الخطر لا يقتصر على "القراءة" فقط؛ فإذا كان الـ API يسمح بطلبات
PUTأوDELETEدون فحص الصلاحية، يمكن للمخترق "تعديل" بيانات مستخدمين آخرين أو حتى "حذف" حساباتهم بالكامل! -
🛡️ تجاوز الحمايات التقليدية: كثير من الأنظمة الأمنية (مثل WAF) لا تكتشف BOLA بسهولة، لأن الطلب يبدو "شرعياً" تماماً؛ المستخدم مسجل دخول، والرابط صحيح، والصيغة سليمة. المشكلة "منطقية" في الكود وليست في شكل الطلب.
هذه هي الطريقة الأكثر ضماناً ودقة:
-
🌐 افتح متصفحين: سجل دخول بالحساب (A) في متصفح، وبالحساب (B) في متصفح آخر.
-
🆔 استخرج المعرف (ID): من الحساب (A)، ابحث عن طلب API يجلب بيانات خاصة، مثل
/api/v1/my-orders/777. -
💥 الهجوم: انسخ رابط الـ API الخاص بالحساب (A)، وحاول تشغيله باستخدام Token أو Cookie الحساب (B).
-
🚨 النتيجة: إذا استجاب السيرفر وأعطاك بيانات الطلب
777للحساب (B)، فأنت أمام ثغرة BOLA صريحة.
أحياناً تكون الـ IDs صعبة التخمين (مثل UUIDs)، لذا ابحث عنها في:
-
📜 ملفات JavaScript: ابحث عن روابط API قديمة أو مخفية في الكود الأمامي (Front-end).
-
🌍 الاستجابات العامة: هل يعرض الموقع الـ ID الخاص بالمستخدمين في التعليقات أو في صفحة "من نحن"؟
-
📱 Mobile Apps: إذا كان للتطبيق نسخة موبايل، افحص طلبات الـ API هناك، غالباً ما تكون الحماية فيها أضعف من نسخة الويب.
لا تكتفِ بطلب الـ GET (القراءة). جرب تغيير الـ Method على نفس الـ ID:
-
✏️ جرب
PUT /api/user/88لتعديل بيانات غيرك. -
🗑️ جرب
DELETE /api/user/88لحذف حساب غيرك. -
🧠 المبدأ: "قد يحمي المبرمج القراءة، لكنه ينسى حماية الحذف والتعديل."
إذا كانت الـ IDs أرقاماً متسلسلة، استخدم أداة Intruder في Burp Suite:
-
🎯 حدد مكان الـ ID في الرابط.
-
🔢 اجعل الـ Payload أرقاماً متسلسلة (مثلاً من 100 إلى 200).
-
📊 راقب الـ HTTP Status Code والـ Length. إذا كانت الأطوال متشابهة، فالسيرفر يسرب البيانات للكل.
هذه هي القاعدة الذهبية. يجب أن يتحقق الكود برمجياً من أن المستخدم الحالي هو صاحب الحق في هذا الـ ID.
-
❌ بدلاً من:
SELECT * FROM orders WHERE id = $id -
✅ الصحيح:
SELECT * FROM orders WHERE id = $id AND user_id = $current_user_id -
🛡️ هنا حتى لو غير الهكر الـ
idلطلب فاتورة شخص آخر، السيرفر سيفشل في إيجاد النتيجة لأنها لا تتبع الـuser_idالخاص به.
توقف عن استخدام الأرقام المتسلسلة (1, 2, 3) التي يسهل تخمينها وعمل "Fuzzing" لها.
- 🧬 استخدم
UUID v4أوGUID. هذا يجعل من الصعب جداً على المخترق تخمين الـ ID الخاص بمستخدم آخر حتى لو كانت الثغرة موجودة منطقياً.
-
🚫 لا تمنح المستخدم صلاحية الوصول لأي Endpoint إلا إذا كان يحتاجه فعلياً.
-
🔑 تأكد من أن الـ Token (مثل JWT) يحتوي على معلومات المستخدم بشكل مشفر ويتم التحقق منه في كل طلب قبل لمس قاعدة البيانات.
بدلاً من كتابة كود التحقق في كل صفحة (مما يسهل نسيان بعض الصفحات)، استخدم "Middleware" أو وظيفة مركزية تقوم بفلترة الطلبات والتأكد من الصلاحيات قبل تمريرها للـ Controller.
-
🧩 قم بإضافة "Integration Tests" في كود الـ Backend تحاكي محاولة وصول مستخدم لمورد لا يملكه.
-
🔍 استخدم أدوات الـ DAST لفحص الـ APIs بشكل دوري لاكتشاف أي ثغرات منطقية تظهر بعد التحديثات.
المخترق المحترف في الـ API يعامل كل "ID" يراه كأنه مفتاح محتمل لغرفة شخص آخر. اسأل نفسك هذه الأسئلة:
-
🔍 أين أجد الـ IDs الأخرى؟
"إذا كان الموقع يستخدمUUIDولا يمكنني تخمينه، من أين يمكنني سرقته؟ هل يظهر في رابط البروفايل العام؟ هل يظهر في الـSource Codeالخاص بالصفحة؟ هل يظهر في تعليقات المستخدمين؟" -
🔄 ماذا لو استبدلت 'معرّفي' بـ 'معرّف الضحية'؟
"أنا الآن أعدل بياناتي الشخصية والطلب يذهب إلى/api/v1/profile/update/105. ماذا يحدث لو أرسلت نفس الطلب لكن غيرت الرقم إلى106؟ هل السيرفر سيسأل: 'هل 105 هو نفسه صاحب الجلسة (Session) الحالية؟' أم سينفذ الأمر فوراً؟" -
🎭 هل هناك 'تبادل أدوار'؟
"أنا مستخدم عادي، والمدير (Admin) له ID. هل يمكنني استخدام الـ Endpoint الخاص بي للوصول لبيانات المدير؟ أو العكس: هل يمكنني استخدام Endpoint مخصص للمديرين وتمرير الـ ID الخاص بي فيه للحصول على صلاحيات أعلى؟" -
🧪 هل الفحص يتم في 'البداية' فقط؟
"الموقع منعني من رؤية صفحة الطلبات الخاصة بغيري عبر المتصفح (Front-end). لكن، ماذا لو أخذت رابط الـ API المباشر واستدعيته عبرBurp SuiteأوPostman؟ هل الحماية موجودة في 'الشكل الخارجي' فقط أم في 'قلب السيرفر'؟"