اختبار التحكم في الوصول

اختبار التحكم في الوصول (Access Control Testing) يتحقق من أن قرار التفويض الذي تعرّفت إليه في درس المصادقة والتفويض مُطبَّق فعلاً في كل طلب: فالخادم يسمح بما تسمح به سياسة الوصول بالضبط، لكل دور وإجراء وسجل، ويرفض ما عداه. وهو اختبار سلبي بطبيعته: تطلب عمداً ما لا يحق للمستخدم الحالي الحصول عليه. ففي تطبيق فواتير، يعيد حساب «المشاهد» إرسال طلب «إرسال الفاتورة» الخاص بالمحاسب بعد نسخه من أدوات المطوّر، ويتوقع 403 مع بقاء الفاتورة دون تغيير.

يتعطّل التحكم في الوصول بثلاث طرق: رأسياً (Vertical) حين ينفّذ دور أدنى وظيفة دور أعلى؛ وأفقياً (Horizontal) حين يصل مستخدم إلى سجل مستخدم آخر في المستوى نفسه، ويُسمّى ذلك مرجعاً مباشراً غير آمن للكائن (IDOR) حين يُعنوَن السجل بمعرّف يستطيع المستدعي تغييره؛ وعلى مستوى الوظيفة (Function-level) حين لا تكون الوظيفة محمية أصلاً. ومصفوفة الأدوار × الإجراءات تحوّل السياسة إلى شروط اختبار تغطي الأنواع الثلاثة.

لماذا يهم

يضع OWASP Top 10:2025 «التحكم في الوصول المعطّل» (Broken Access Control) في المرتبة الأولى (A01)، ويبدأ OWASP API Security Top 10 (2023) بالتفويض المعطّل على مستوى الكائن (API1) ويدرج أيضاً التفويض المعطّل على مستوى الوظيفة (API5). فالمستخدمون الحقيقيون يتبعون الشاشات المصممة لدورهم، لذا لا يرسل الاختبار الذي يتبع تلك الشاشات أبداً الطلبات التي تكشف هذه العيوب، ومعرّف واحد مغيَّر قد يكشف بيانات كل الزبائن.

وبالنسبة إلى المختبِر، هذه الاختبارات زهيدة الكلفة وعالية القيمة: حسابا اختبار وأداة لإرسال الطلبات، ونتائج متوقعة تحددها السياسة فتسهل أتمتتها، ونتائج كثيراً ما تُصنَّف خطورتها حرجة (Critical) أو رئيسية (Major) لأنها تكشف بيانات أو إجراءات تعود لشخص آخر.

الإخفاقات الرأسية والأفقية وعلى مستوى الوظيفة

يجيب التفويض عن سؤال واحد في كل طلب: هل يحق لهذه الهوية تنفيذ هذا الإجراء على هذا المورد؟ وللفحص مستويان: فحص على مستوى الوظيفة يسأل هل يحق لهذا الدور استدعاء هذه الوظيفة أصلاً (دعوة مستخدم، تصدير كل الفواتير)، وفحص على مستوى الكائن يسأل هل يحق لهذا المستخدم التصرف في هذا السجل بعينه (الفاتورة 3107 لا 3108). ويُسمّى إخفاقان منها بحسب الاتجاه الذي يكسب فيه المستدعي الوصول، والثالث بحسب الفحص المفقود.

  • تصعيد الامتيازات الرأسي: دور أدنى يستخدم وظيفة دور أعلى، مثلاً «مشاهد» يرسل طلب المالك POST /api/users. الفحص مفقود أو يثق بالعميل، كدور يُنقل في كوكي أو في جسم الطلب. المتوقع: 403 ولا يحدث شيء.
  • تصعيد الامتيازات الأفقي: الدور نفسه وسجل شخص آخر. محاسب في الشركة A يغيّر رقماً واحداً ويطلب GET /api/invoices/3108، وهي فاتورة للشركة B. تسمّي OWASP ذلك مرجعاً مباشراً غير آمن للكائن (IDOR)، ويسمّي OWASP API Security Top 10 العيب نفسه تفويضاً معطّلاً على مستوى الكائن (BOLA). المتوقع: 403، أو 404 حين يخفي العقد سجلات الزبائن الآخرين.
  • غياب التحكم في الوصول على مستوى الوظيفة: وظيفة لا يحميها سوى الخفاء. الرابط غير معروض، أو نقطة النهاية غير موثّقة، أو /api/v1/export القديم ما زال يجيب، أو الفحص يغطي GET دون DELETE على العنوان نفسه. المتوقع: 401 أو 403 كما تقول السياسة؛ وأي نجاح عيب. وغياب الفحص على مستوى الوظيفة هو أيضاً السبب المعتاد للتصعيد الرأسي، لكن الاسم المستقل يُبقي انتباهك على الوظائف التي لا تعرضها أي شاشة ولا تذكرها أي قائمة.
  • وهناك مستوى أدق: مستخدم يحق له تحديث سجل فيغيّر حقلاً ليس له، مثل "role": "owner" في تحديث الملف الشخصي، وهو ما يسمّيه OWASP API Security Top 10 التفويض المعطّل على مستوى خصائص الكائن (API3:2023). أبقِه في قائمتك، ويتوسع فيه درس اختبار أمان الواجهات البرمجية.

جرّبها: منشئ طلبات API

من سياسة الوصول إلى مصفوفة الأدوار × الإجراءات

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

املأ كل خلية بالنتيجة المتوقعة قبل أن ترسل أي شيء: رمز النجاح والأثر الظاهر للخلية المسموحة، والرمز و«لا أثر جانبي» للخلية المرفوضة. كل خلية شرط اختبار: فالخلية المرفوضة التي يعود إجراؤها لدور أعلى اختبار رأسي؛ والخلية المسموحة التي تسمّي سجلاً تُكرَّر بسجل مستخدم آخر بوصفها الاختبار الأفقي؛ وكل عمود يُطلب مباشرةً في كل صف بوصفه اختبار مستوى الوظيفة. وتطلب ورقة OWASP الإرشادية للتفويض (Authorization Cheat Sheet) من الفِرق كتابة اختبارات وحدة وتكامل لمنطق التفويض؛ والمصفوفة هي المصدر المشترك لتلك الاختبارات ولاختباراتك.

جرّبها: مولّد حالات اختبار من OpenAPI

مثال تطبيقي: تطبيق فواتير بثلاثة أدوار

خدمة فواتير على https://invoices.test، في بيئة اختبار لديك إذن كتابي باختبارها، تخدم شركات كثيرة. السياسة: «ينتمي المستخدم إلى شركة واحدة ولا يرى إلا بياناتها؛ وأي طلب يخص فاتورة شركة أخرى يعيد 404. المشاهدون يقرؤون الفواتير. والمحاسبون ينشئون الفواتير ويرسلونها أيضاً. والمالكون يصدّرون كل الفواتير ويدعون المستخدمين أيضاً. وبلا جلسة صالحة تعيد الواجهة 401». حسابات الاختبار: مها (مشاهدة) ويوسف (محاسب) ورنا (مالكة) في الشركة A التي تملك الفاتورة 3107، وطارق (محاسب) في الشركة B.

سجّل الدخول بحساب رنا، ونفّذ كل إجراء من الإجراءات الخمسة مرة واحدة، وانسخ كل طلب يرسله الإجراء من لوحة الشبكة بصيغة cURL؛ ففتح الفاتورة 3107 مثلاً يحمّل أيضاً معاينتها بصيغة PDF من GET /api/invoices/3107/pdf. ثم أعد إرسال كل طلب في أداة طلبات بكوكي جلسة مها ثم يوسف ثم طارق على التوالي، ومرة أخيرة بلا كوكي، دون تغيير أي شيء آخر. وإن حمل الطلب أيضاً رمزاً مرتبطاً بجلسة رنا، كرمز مكافحة CSRF، فبدّله كذلك، وإلا فقد يأتي الرفض من فحص ذلك الرمز لا من التفويض. كشفت الجولة عيبين.

مصفوفة الوصول لتطبيق الفواتير: من 24 خلية تجمع المستدعي والإجراء لا يُسمح إلا بـ 9؛ ويتلقى المشاهد 403 لكل إجراء من إجراءات المحاسب والمالك، ويتلقى محاسب الشركة B الرمز 404 للفاتورة 3107 الخاصة بالشركة A.
المستدعيA1 · عرض الفاتورة 3107GET /api/invoices/3107A2 · إنشاء فاتورةPOST /api/invoicesA3 · إرسال الفاتورة 3107POST /api/invoices/3107/sendA4 · تصدير كل الفواتيرGET /api/export/invoices.csvA5 · دعوة مستخدمPOST /api/users
مجهول الهويةبلا جلسة401المصادقة401المصادقة401المصادقة401المصادقة401المصادقة
مها · مشاهدةالشركة A200مسموح403رأسي403رأسي403رأسي403رأسي
يوسف · محاسبالشركة A200مسموح201مسموح200مسموح403رأسي403رأسي
رنا · مالكةالشركة A200مسموح201مسموح200مسموح200مسموح201مسموح
طارق · محاسبالشركة B، على فاتورة الشركة A404أفقي (IDOR)لا سجل للشركة A في هذا الإجراء404أفقي (IDOR)403رأسي403رأسي
  • مسموح وفق السياسة، مع رمز النجاح المتوقع
  • اختبار رأسي: 403 لوظيفة أعلى من دور المستدعي
  • اختبار أفقي (IDOR): 404 لفاتورة شركة أخرى يخفيها العقد
  • المصادقة: 401 بلا جلسة صالحة

نتائج متوقعة مكتوبة من السياسة قبل إرسال أي طلب: المشاهدون يقرؤون الفواتير؛ والمحاسبون ينشئونها ويرسلونها أيضاً؛ والمالكون يصدّرون كل الفواتير ويدعون المستخدمين أيضاً؛ وفاتورة شركة أخرى تعيد 404.

  • إعادة مها إرسال POST /api/invoices/3107/send أعادت 200 ووصلت الفاتورة إلى الزبون: تصعيد رأسي؛ فالفحص كان موجوداً في القائمة فقط. الخطورة: حرج (Critical).
  • طلب طارق GET /api/invoices/3107 أعاد 404 كما يجب، لكن طلب المعاينة GET /api/invoices/3107/pdf أعاد ملف PDF: تصعيد أفقي عبر مسار ثانٍ إلى السجل نفسه. الخطورة: حرج.
  • طابقت كل الخلايا الأخرى المصفوفة. أكّد كل إصلاح بإعادة تشغيل العمود كاملاً، لا الخلية التي فشلت وحدها.
النسخة النصية
Expected result per cell, written from the policy before any request is sent

Caller                 A1 view 3107  A2 create  A3 send 3107  A4 export  A5 invite
Anonymous              401           401        401           401        401
Maha, viewer A         200           403        403           403        403
Yousef, accountant A   200           201        200           403        403
Rana, owner A          200           201        200           200        201
Tariq, accountant B    404           -          404           403        403

401 = authentication (no session)    403 = vertical: a function above the role
404 = horizontal: Company B's user on Company A's invoice (the contract hides it)

جرّبها: محلّل أوامر cURL جرّبها: مختبِر مصادقة API جرّبها: مقارنة استجابات API

أين تختبئ الوظائف والمعرّفات غير المحمية

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

  • مسارات أخرى إلى السجل نفسه: عرض PDF أو عرض الطباعة، ونقطة نهاية للبحث بمرشّح company، وتصدير جماعي، ورابط مشاركة.
  • طرق وإصدارات أخرى للعنوان نفسه: فحص على GET دون PUT أو DELETE، أو إصدار قديم من الواجهة ما زال منشوراً.
  • قيم يرسلها العميل عن نفسه: companyId أو role أو isOwner في الجسم أو سلسلة الاستعلام أو كوكي أو حقل مخفي. على الخادم أن يأخذ الهوية والشركة من الجلسة؛ غيّر هذه القيم وتوقّع تجاهلها أو رفضها.
  • الملفات والمعرّفات العشوائية: ملف PDF مرفوع يُقدَّم من عنوان تخزين دون فحص الجلسة، أو UUID يصعب تخمينه. كلاهما يخفي السجل ولا يفوّض قارئه. انسخ معرّفاً حقيقياً من حساب الاختبار الآخر وتوقّع الرفض.

جرّبها: مختبِر REST API

أخطاء شائعة

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

من منظور ضمان الجودة

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

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

تمرين عملي

ابنِ مصفوفة الوصول لمنصة دورات تعليمية

المطلوب

منصة دورات لها ثلاثة أدوار. المتعلمون لا يرون إلا تسليماتهم وشهاداتهم. والمدرّسون يرون قائمة متعلمي الدورات التي يدرّسونها، ويرون تسليماتها ويقيّمونها، ويرون شهاداتها. والمسؤولون يفعلون كل شيء وهم وحدهم من يُجري استرداد المدفوعات. تعيد الواجهة 401 بلا جلسة صالحة، و403 لوظيفة لا يحق للدور استخدامها، و404 لسجل يعود لمتعلم آخر أو دورة أخرى. ولديك إذن كتابي باختبار بيئة الاختبار.

ابنِ مصفوفة المستدعين مقابل الإجراءات الخمسة في المادة، وتوقّع رمز كل خلية، وصنّف كل خلية مرفوضة: مصادقة أو رأسي أو أفقي. ثم أضف ثلاثة اختبارات من قسم الوظائف المخفية.

المادة
Setup: submission 4410 = learner Lina, course QA-101 (instructor Hani)
       certificate 7702 = learner Omar, course DB-201 (instructor Dana)
       Lina and Omar are learners; Hani and Dana are instructors; Sami is an admin

#  Action                     Request
A1 view submission 4410       GET  /api/submissions/4410
A2 grade submission 4410      POST /api/submissions/4410/grade
A3 download certificate 7702  GET  /api/certificates/7702
A4 list learners of QA-101    GET  /api/courses/QA-101/learners
A5 refund a payment           POST /api/payments/88/refund
الخطوات
  1. اكتب المستدعين: مجهول الهوية، وكل دور، ومستخدماً ثانياً بالدور نفسه للحالة الأفقية.
  2. اكتب الإجراءات من كل مصدر، بما فيها ما لا يراه المتعلم أبداً.
  3. املأ كل خلية من السياسة قبل أن تنظر إلى النظام.
  4. صنّف كل خلية مرفوضة: مصادقة (401) أو رأسي (403) أو أفقي (404).
  5. أضف اختبارات للمسارات والطرق الأخرى والقيم التي يرسلها العميل.
إظهار الإجابة النموذجية
الإجابة النموذجية

مجهول الهوية: 401 في كل عمود (مصادقة). سامي، المسؤول: مسموح في كل عمود، 200 للقراءات و200 أو 201 للتقييم والاسترداد كما يحدد العقد.

لينا، متعلمة وصاحبة التسليم 4410: A1 200؛ A2 403 (رأسي: المتعلمون لا يقيّمون أبداً)؛ A3 404 (أفقي: شهادة عمر)؛ A4 403 وA5 403 (رأسي).

عمر، متعلم: A1 404 (أفقي، خلية IDOR الكلاسيكية)؛ A2 403 (رأسي)؛ A3 200؛ A4 403 وA5 403 (رأسي).

هاني، مدرّس QA-101: A1 200؛ A2 مسموح (200 أو 201 كما يحدد العقد) ثم تأكد من تخزين التقييم؛ A3 404 (أفقي: شهادة من دورة دانا)؛ A4 200؛ A5 403 (رأسي: الاسترداد للمسؤولين فقط).

دانا، مدرّسة DB-201: A1 وA2 404 (أفقي: تسليم من دورة أخرى، مع بقاء التقييم دون تغيير)؛ A3 200؛ A4 404 (أفقي: دورة مدرّس آخر)؛ A5 403 (رأسي).

اختبارات الوظائف المخفية، مثلاً: لينا تطلب شهادة عمر بصيغة ملف GET /api/certificates/7702/pdf وتتوقع 404 ولا ملف؛ ولينا ترسل DELETE /api/submissions/4410 وتتوقع 403 أو 405 كما يحدد العقد ولا تغيير؛ ودانا تقيّم 4410 مع "courseId": "DB-201" في الجسم وتتوقع 404 مع بقاء التقييم دون تغيير.

أسئلة شائعة

هل IDOR هو نفسه تصعيد الامتيازات الأفقي؟

IDOR هو الصورة المعتادة للتصعيد الأفقي: سجل يُعنوَن بمعرّف يستطيع المستدعي تغييره، والخادم لا يفحص الملكية. ويحدث التصعيد الأفقي أيضاً عبر مرشّحات البحث والتصدير وروابط المشاركة التي تعيد سجلات مستخدمين آخرين دون تعديل أي معرّف. ويجمع OWASP API Security Top 10 هذه كلها تحت التفويض المعطّل على مستوى الكائن (BOLA).

كم حساب اختبار أحتاج؟

حساباً واحداً على الأقل لكل دور، ومستخدماً إضافياً بالدور نفسه في فريق أو شركة أخرى للصف الأفقي، وكلها في بيئة اختبار وليست حسابات مستخدمين حقيقيين أبداً. وفي المنتجات متعددة المستأجرين (Multi-tenant)، حيث يخدم نظام واحد شركات كثيرة، تحتاج إلى شركتين لكل منهما سجلاتها، كي يكون لكل إجراء مرتبط بسجل سجلٌ يعود لشخص آخر.

هل تجعل معرّفات UUID العشوائية اختبارات IDOR غير ضرورية؟

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

المراجع

  • OWASP Web Security Testing Guide (WSTG)OWASP Foundationالمنهجية المرجعية لاختبار تطبيقات الويب وواجهات API بحثاً عن نقاط الضعف الأمنية، اختباراً تلو الآخر.
  • OWASP Top 10:2025OWASP Foundation · 2025أخطر عشرة مخاطر أمنية لتطبيقات الويب، مع كيفية اختبار كل منها والوقاية منه.
  • OWASP Cheat Sheet Series: AuthorizationOWASP Foundationضبط الوصول بالشكل الصحيح: أقل الصلاحيات، والرفض افتراضياً، والتحقق من الصلاحيات في كل طلب، وتفضيل النماذج المبنية على السمات أو العلاقات، واختبار منطق التفويض.
  • OWASP API Security Top 10 (2023)OWASP Foundation · 2023أكثر عشر نقاط ضعف شيوعاً في واجهات API: خلل التفويض على مستوى الكائن، وخلل التوثيق، والاستهلاك غير المقيد للموارد، وغيرها.

تدرّب بأدوات متقن

أنشئ طلبات HTTP وأرسلها (الطريقة وعنوان URL والترويسات والمصادقة والجسم) وافحص الاستجابة — بديل خفيف لـ Postman داخل متصفحك.

اختبار واجهات API

اختبر مصادقة Bearer وBasic ومفتاح API والترويسات المخصّصة على نقطة نهاية وقارن الاستجابات المصرّح بها بغير المصرّح بها.

اختبار واجهات API

اختبر نقاط نهاية REST بتحكم كامل في الطريقة والترويسات وجسم JSON، ثم أضف تأكيدات على الحالة والترويسات ومسارات JSON.

اختبار واجهات API

قارن استجابتي API (مثل بيئة التجريب مقابل الإنتاج) واحصل على قائمة بكل فرق بنيوي أو في القيم.

اختبار واجهات API

تحليل أمر cURL إلى الطريقة وعنوان URL والترويسات والمتن، ثم تحويله إلى fetch أو axios أو Python أو طلب منظّم.

الويب

للتعمّق أكثر

تقدّمك في هذا الموضوع

جزء من مسار تعلم ضمان الجودة