کنترل دسترسی شکسته چیست؟
کنترل دسترسی (Access Control) سازوکاری است که تعیین میکند هر کاربر — چه احراز هویت شده باشد چه نشده — مجاز به دیدن، تغییر یا حذف کدام داده و اجرای کدام عملیات است. «شکسته بودن» این کنترل بهندرت بهمعنای نبودِ کامل سیاست است؛ تقریباً همیشه یعنی سیاست وجود دارد اما در نقطهی درست اعمال نمیشود.
برای فهم مکانیزم، به سه نقطهای فکر کنید که یک برنامهی وب معمول میتواند تصمیم مجوزدهی بگیرد:
- رابط کاربری: دکمهی «حذف» برای کاربر عادی رندر نمیشود.
- لایهی مسیریابی یا Gateway: نقش
userاجازهی رسیدن به مسیر/admin/*را ندارد. - لایهی دسترسی به داده: این رکورد مشخص، متعلق به همین کاربر است یا نه.
اکثریت قاطع یافتههای کنترل دسترسی از آنجا میآیند که دو نقطهی اول پیادهسازی شده و نقطهی سوم فراموش شده است. رابط کاربری یک کنترل امنیتی نیست. Gateway هم میداند کاربر به کدام مسیر دسترسی دارد، اما نمیداند به کدام رکورد. تصمیم واقعی باید همانجا گرفته شود که داده خوانده یا نوشته میشود.
OWASP در دادهی نسخهی ۲۰۲۵ آماری منتشر کرده که ارزش نقلکردن دارد: ۱۰۰٪ برنامههای آزمودهشده نوعی نقص کنترل دسترسی داشتهاند. این عدد بهمعنای «همهی برنامهها بحرانیاند» نیست، اما بهروشنی میگوید این دسته را نمیتوان با فرض «ما مرتب هستیم» رد کرد.
انواع نقص کنترل دسترسی
سه محور اصلی برای دستهبندی وجود دارد:
| نوع | معنا | مثال |
|---|---|---|
| ارتقای عمودی (Vertical) | کاربر کمدسترسی به عملیات نقشی بالاتر میرسد | کاربر عادی POST /api/users/7/role را با مقدار admin اجرا میکند |
| ارتقای افقی (Horizontal) | کاربر به دادهی همسطح خودش اما متعلق به شخص دیگر میرسد | تغییر ?invoice=1041 به 1042 و دیدن فاکتور مشتری دیگر |
| وابسته به زمینه (Context-dependent) | کاربر مرحلهای از یک فرایند چندمرحلهای را رد میکند | رسیدن مستقیم به مرحلهی «تأیید سفارش» بدون گذر از مرحلهی پرداخت |
و الگوهای اجرایی که این سه محور از دل آنها بیرون میآیند:
- مرور اجباری (Forced Browsing): باز کردن مستقیم مسیری که هیچ لینکی به آن وجود ندارد —
/admin/getAppInfo،/reports/export، نسخههای قدیمی API مثل/api/v1/که پس از انتشارv2بدون کنترل باقی ماندهاند. «لینکنشده بودن» یک کنترل امنیتی نیست. - دستکاری پارامتر (Parameter Tampering): تغییر شناسه در مسیر، Query String، بدنهی JSON، کوکی یا حتی ادعای داخل توکن JWT. حالت خاص و پرتکرار آن IDOR است.
- اتکا به کنترل سمت کلاینت: دکمه پنهان است، فیلد
disabledاست، یا مسیر در روتر جاوااسکریپتی محافظت شده — اما همان درخواست با یک ابزار خط فرمان بدون هیچ مانعی اجرا میشود. - ناهماهنگی متدها و مسیرهای موازی: بررسی مجوز روی
GETهست ولی رویPUT/DELETEنیست؛ یا روی صفحهی HTML هست ولی روی اندپوینت JSON معادلش نیست. - دور زدن ACL لبه: هدرهایی مثل
X-Original-URLوX-HTTP-Method-Override، یا اختلاف نرمالسازی مسیر بین پروکسی جلویی و اپلیکیشن پشتی.
چه چیزی در نسخهی ۲۰۲۵ تغییر کرد
در OWASP Top 10:2025 این دسته با ۴۰ CWE بزرگترین دستهی فهرست است و دو تغییر ساختاری مهم دارد. صفحهی رسمی A01:2025 تصریح میکند که SSRF (یعنی CWE-918) — که در نسخهی ۲۰۲۱ دستهی مستقل A10 بود — در این دسته ادغام شده، و CSRF (یعنی CWE-352) هم اینجا قرار دارد.
منطق ادغام قابل دفاع است: در SSRF مهاجم سرور را وادار میکند از طرف او به منبعی برسد که حق دسترسی به آن را ندارد، و در CSRF مرورگر قربانی وادار میشود عملیاتی را با مجوز قربانی اجرا کند. هر دو در ماهیت، شکست در اعمال مرز اعتماد هستند.
در راهنمای آزمون OWASP یعنی WSTG v4.2، آزمون SSRF همچنان زیر بخش اعتبارسنجی ورودی (WSTG-INPV) قرار دارد و نه زیر مجوزدهی (WSTG-ATHZ). این دو تاکسونومی همراستا نیستند و در گزارش تست نفوذ نباید طوری ارائه شوند که انگار هستند. ما در گزارشهای تست نفوذ پوشش آزمون را با شناسهی WSTG و ردهبندی ریسک را با Top 10:2025 بیان میکنیم.
CWEهای شاخص این دسته: CWE-862 (نبود مجوزدهی)، CWE-285 (مجوزدهی نادرست)، CWE-200 و CWE-201 (افشای اطلاعات حساس)، بهعلاوهی CWE-918 و CWE-352. در فهرست ۲۰۲۵ CWE Top 25 هم CWE-352 رتبهی سوم و CWE-862 رتبهی چهارم را دارند.
سناریوی واقعی
یک سامانهی فروش سازمانی با سه نقش: agent، manager و admin. پنل مدیریت با یک روتر سمت کلاینت ساخته شده و برای نقش agent هیچ آیتم منویی از بخش «گزارشها» رندر نمیشود. تیم توسعه این را کنترل دسترسی میداند.
در تست نفوذ، فایلهای جاوااسکریپت بستهبندیشده بررسی میشوند. داخل باندل، تعریف مسیرها و آدرس اندپوینتهای API آنها بهطور کامل موجود است — از جمله /api/reports/export?scope=all. ارسال همان درخواست با نشست نقش agent پاسخ 200 و خروجی کامل گزارش فروش همهی شعب را برمیگرداند. بررسی نقش فقط در رندر منو بوده، نه در کنترلر.
یافتهی دوم روی PATCH /api/users/{id} است: بررسی مالکیت وجود دارد و کاربر فقط پروفایل خودش را تغییر میدهد، اما بدنهی درخواست مستقیماً به شیء کاربر نگاشت میشود و افزودن فیلد "role":"admin" پذیرفته میشود — الگوی Mass Assignment: مالکیت کنترل شده، اما ویژگیهای قابل نوشتن محدود نشدهاند. هیچکدام از این دو با اسکنر خودکار کشف نمیشد، چون ابزار نمیداند نقش agent باید به چه چیزی دسترسی داشته باشد.
چگونه در تست نفوذ کشف میشود
روش استاندارد، آزمون تفاضلی با چند حساب است. مراحل عملی:
- نگاشت نقشها: برای هر نقش حداقل یک حساب بگیرید، و برای آزمون افقی دو حساب همسطح. بدون حساب دوم، آزمون افقی عملاً ممکن نیست.
- ساخت نقشهی کامل درخواستها: با هر حساب کل برنامه را پیمایش کنید. باندلهای جاوااسکریپت، فایلهای
.mapو مستندات OpenAPI را برای اندپوینتهای نامرئی در رابط کاربری بررسی کنید؛ ffuf برای کشف مسیرهای لینکنشده و نسخههای قدیمی API مفید است. - بازپخش متقاطع: هر درخواست نقش بالا را با نشست نقش پایین دوباره بفرستید و برعکس. افزونههای خانوادهی Autorize در Burp Suite و امکانات مشابه در Caido این مقایسه را خودکار میکنند، اما تفسیر نتیجه دستی است.
- آزمون متدها و ویژگیها: اگر
GETمحافظت شده، همان منبع را باPUT،DELETEو هدرهای Method Override بیازمایید؛ و فیلدهای اضافی مثلroleیاtenantIdرا به بدنهی درخواست اضافه کنید.
نکتهای که باید صریح گفته شود: هیچ اسکنر خودکاری کنترل دسترسی را قابل اتکا پیدا نمیکند، چون ابزار نمیتواند بداند چه چیزی باید مجاز باشد. به همین دلیل این حوزه بیشترین ارزش را در تست نفوذ دستی دارد.
نمونهی فنی
شکل تفاضلی یافته در گزارش، معمولاً همین است — دو درخواست یکسان با دو نشست متفاوت:
GET /api/v1/invoices/1042 HTTP/1.1
Host: app.example.com
Cookie: session=<session-of-user-A>
HTTP/1.1 200 OK
{"id":1042,"owner":"user-B","total":48900000}پاسخ باید 403 Forbidden میبود. نکتهی مهم در گزارشنویسی این است که شواهد باید مالکیت رکورد را نشان دهد، نه صرفاً کد وضعیت ۲۰۰ — یعنی باید ثابت شود رکورد ۱۰۴۲ واقعاً متعلق به کاربر دیگری است. برای الگوی Mass Assignment هم شکل سادهی اثبات مفهوم این است:
PATCH /api/users/501 HTTP/1.1
Content-Type: application/json
{"displayName":"test","role":"admin"}
اشتباهات رایج
«فایروال برنامهی وب جلوی کنترل دسترسی شکسته را میگیرد.» نمیگیرد. WAF یک فیلتر مبتنی بر امضا و الگوی درخواست است؛ درخواست GET /api/invoices/1042 از نظر آن کاملاً عادی و بیخطر است، چون WAF هیچ تصوری از مدل مالکیت دادهی شما ندارد. «نصب WAF» هرگز نباید بهعنوان راهکار رفع یک نقص کنترل دسترسی در گزارش تست نفوذ نوشته شود — حداکثر یک اقدام جبرانی موقت است.
دو اشتباه پرتکرار دیگر:
- «مسیرش لینک نشده، پس امن است.» مسیرهای لینکنشده از باندل جاوااسکریپت، فایلهای
.map، آرشیوهای اینترنتی، مخازن گیت و پیامهای خطا بیرون میآیند. این «امنیت از راه ابهام» است، نه کنترل دسترسی. - «بررسی در Middleware است، پس همهجا اعمال میشود.» فقط وقتی درست است که هیچ مسیری از Middleware عبور نکند و بررسی در سطح رکورد هم انجام شود. اندپوینتهای داخلی، Webhookها و نسخههای قدیمی API معمولاً از این زنجیره خارجاند.
پرسشهای متداول
تفاوت کنترل دسترسی شکسته با IDOR چیست؟
IDOR یک زیرمجموعه از کنترل دسترسی شکسته است، نه یک دستهی جداگانه. IDOR حالتی است که برنامه از شناسهای که کاربر تعیین میکند برای ارجاع به یک شیء استفاده میکند و مالکیت آن شیء را بررسی نمیکند. کنترل دسترسی شکسته چتر بزرگتری است که ارتقای عمودی، مرور اجباری، Mass Assignment و دور زدن مرحلههای فرایند را هم شامل میشود.
چرا SSRF و CSRF به دستهی کنترل دسترسی منتقل شدند؟
چون هر دو در ماهیت شکست در اعمال مرز اعتماد هستند. صفحهی رسمی A01:2025 تصریح میکند که SSRF (CWE-918) در این دسته ادغام شده و CSRF (CWE-352) هم زیر همین دسته قرار دارد. این تغییر اهمیت فنی هیچکدام را کم نمیکند؛ فقط جای آنها را در تاکسونومی ریسک عوض میکند.
آیا اسکنر خودکار میتواند نقص کنترل دسترسی را پیدا کند؟
بهصورت قابل اتکا خیر. اسکنر نمیداند کدام کاربر باید به کدام رکورد دسترسی داشته باشد، بنابراین نمیتواند تفاوت پاسخ مجاز و غیرمجاز را تشخیص دهد. ابزارهایی مثل افزونههای بازپخش متقاطع در Burp کار مقایسه را خودکار میکنند، اما تعریف سیاست و تفسیر نتیجه دستی است. به همین دلیل این حوزه پرارزشترین بخش تست نفوذ دستی است.
شدت یک یافتهی کنترل دسترسی چقدر است؟
بستگی به داده و عملیاتی دارد که در دسترس قرار میگیرد. خواندن دادهی یک کاربر دیگر معمولاً متوسط تا بالا امتیاز میگیرد؛ ارتقای عمودی به نقش مدیر یا دسترسی به دادهی همهی مستأجرها معمولاً بحرانی است. امتیازدهی را با CVSS انجام دهید و در گزارش صراحتاً بنویسید از کدام نسخه استفاده کردهاید.