۱. هدف این آموزش چیست؟
در پایان این آموزش، کاربر باید بتواند:
-
مفهوم احراز هویت (Authentication) و مجوز دسترسی (Authorization) را از هم تشخیص دهد.
-
نقاط احتمالی IDOR را در یک برنامه وب شناسایی کند.
-
درخواستهای HTTP و پاسخهای سرور را با ابزارهای توسعه مرورگر یا Burp Suite بررسی کند.
-
در یک محیط آزمایشگاهی، دسترسی کاربر به منابع متعلق به کاربران دیگر را آزمایش کند.
-
تفاوت یک شناسه قابل حدس با یک آسیبپذیری واقعی را بفهمد.
-
آسیبپذیری را بهدرستی مستند کند و راهکار اصلاح آن را ارزیابی کند.
پیشنیازها: آشنایی مقدماتی با HTTP، مرورگر، درخواستهای GET و POST و مفاهیم پایه وب. آشنایی با خط فرمان لینوکس مفید است، اما ضروری نیست.
۲. IDOR دقیقاً چیست؟
IDOR مخفف Insecure Direct Object Reference است. این آسیبپذیری زمانی رخ میدهد که برنامه یک شناسه را از کاربر دریافت میکند، اما بررسی نمیکند که کاربر فعلی مجاز به دسترسی به شیء موردنظر هست یا خیر. این موضوع یکی از حالتهای نقض کنترل دسترسی است.
برای مثال، تصور کنید یک فروشگاه اینترنتی برای مشاهده سفارش از آدرس زیر استفاده میکند:
GET /api/orders/501
کاربر وارد حساب خود شده و سفارش شماره 501 را مشاهده میکند. اگر برنامه فقط بررسی کند که کاربر وارد حساب شده است، اما مالکیت سفارش را بررسی نکند، ممکن است همان کاربر بتواند سفارش متعلق به شخص دیگری را مشاهده کند.
نکته مهم این است که تغییر شناسه بهتنهایی اثبات آسیبپذیری نیست. آسیبپذیری زمانی تأیید میشود که سرور واقعاً دسترسی غیرمجاز به داده یا عملیاتی را مجاز بداند.
نمونههای متداول IDOR
۱. سفارشهای کاربران
کاربر بتواند اطلاعات سفارش، نشانی تحویل یا وضعیت خرید متعلق به حساب دیگری را ببیند.
۲. پروفایل و اطلاعات حساب
شناسه پروفایل در URL یا API تغییر کند و اطلاعاتی فراتر از مجوز کاربر نمایش داده شود.
۳. فایلها و اسناد خصوصی
شناسه فایل عوض شود و برنامه سند خصوصی متعلق به کاربر دیگری را برگرداند.
۴. تیکتهای پشتیبانی
یک کاربر بتواند مکاتبات خصوصی یا تیکتهای کاربران دیگر را مشاهده یا تغییر دهد.
۳. تفاوت Authentication و Authorization
این تفاوت، اساس درک IDOR است.
| مفهوم | پرسشی که پاسخ میدهد | مثال |
|---|---|---|
| Authentication | چه کسی هستی؟ | کاربر با حساب خود وارد شده است. |
| Authorization | چه اجازهای داری؟ | آیا اجازه مشاهده سفارش 501 را داری؟ |
| IDOR | آیا مجوز دسترسی به همان شیء بررسی میشود؟ | آیا سفارش واقعاً متعلق به کاربر فعلی است؟ |
یک برنامه میتواند ورود کاربران را کاملاً درست انجام دهد، اما همچنان IDOR داشته باشد. وجود نشست معتبر، مجوز دسترسی به تمام شناسههای موجود در سامانه را ایجاد نمیکند.
۴. آمادهسازی محیط آزمایشگاه
دو مسیر برای تمرین داریم: یک محیط محلی ساختگی برای فهم دقیق کنترل دسترسی و یک آزمایشگاه آماده برای تمرین بیشتر.
مسیر اول: آزمایشگاه محلی
مناسب برای تمرین درخواست و پاسخ، مشاهده خطا و بررسی منطق مجوزها.
مسیر دوم: آزمایشگاه آموزشی آماده
مناسب برای تمرین روی سناریوهای واقعیتر و مرحلهبندیشده.
منبع پیشنهادی: آموزش IDOR در PortSwigger Web Security Academy؛ این مجموعه آموزش و آزمایشگاههای تعاملی رایگان دارد.
ابزارهای موردنیاز
-
مرورگر بهروز مثل Firefox یا Chrome
-
ابزار Developer Tools مرورگر، بهویژه بخش Network
-
Burp Suite Community Edition برای مشاهده و بازفرستادن درخواستهای آزمایشگاهی
-
یک برنامه وب آسیبپذیرِ عمدی یا برنامه محلی که خودتان کنترل میکنید
اگر از Burp Suite استفاده میکنید، فقط ترافیک مرورگر آزمایشگاهی خود را از پروکسی عبور دهید. در این تمرین نیازی به اسکن خودکار یا ارسال انبوه درخواستها نیست.
۵. ساخت سناریوی عملی با دو کاربر
در این سناریو، یک برنامه فرضی مدیریت سفارشها داریم:
-
کاربر A: مالک سفارش 501
-
کاربر B: مالک سفارش 502
-
هر سفارش شامل اطلاعات ساختگی است.
-
هدف آزمایش: بررسی اینکه آیا کاربر A میتواند سفارش متعلق به B را بخواند یا خیر.
ساختار درخواست
فرض کنید API این مسیر را دارد:
GET /api/orders/501 HTTP/1.1
Host: localhost:5000
Cookie: session=LAB_SESSION_A
پاسخ مجاز برای کاربر A:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": 501,
"owner": "user_a",
"item": "Keyboard",
"status": "shipped"
}
این پاسخ بهتنهایی نشاندهنده آسیبپذیری نیست؛ کاربر A مالک سفارش 501 است.
فرضیه تست نفوذ
اکنون میخواهیم بررسی کنیم که برنامه، مالکیت هر سفارش را در سمت سرور بررسی میکند یا صرفاً وجود شناسه سفارش را.
در یک آزمایشگاه مجاز، درخواست را با حساب آزمایشی A و شناسه سفارش B بررسی میکنیم. در یک برنامه آسیبپذیر ممکن است چنین پاسخی دیده شود:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": 502,
"owner": "user_b",
"item": "Monitor",
"status": "processing"
}
اگر این پاسخ واقعاً از سرور دریافت شود و کاربر A مجوز مشاهده سفارش 502 را نداشته باشد، شاهدی قوی از IDOR داریم.
در پیادهسازی امن، سرور باید درخواست را رد کند؛ برای نمونه با پاسخ 403 Forbidden یا 404 Not Found، مطابق سیاست امنیتی برنامه. مهم این است که داده خصوصی در پاسخ افشا نشود.
۶. اجرای تست با مرورگر و Burp Suite
مرحله اول: شناسایی نقاط ورودی
در محیط آزمایشگاهی، وارد حساب تست شوید و بخشهایی را بررسی کنید که منابع خاصی را بارگذاری میکنند.
به دنبال مواردی مثل اینها باشید:
/orders/501
/api/orders/501
/profile?id=101
/api/tickets/204
/download?file_id=72
این مسیرها فقط نمونه هستند، نه آدرسهای واقعی. هر پارامتر شناسهای الزاماً آسیبپذیر نیست؛ هدف، پیدا کردن نقاطی است که سرور باید برای آنها مجوز دسترسی بررسی کند.
مرحله دوم: مشاهده درخواست
در مرورگر:
-
Developer Tools را باز کنید.
-
وارد زبانه Network شوید.
-
صفحه سفارش متعلق به حساب آزمایشی خود را باز کنید.
-
درخواست مربوط به سفارش را پیدا کنید.
-
مسیر، پارامترها، کوکی نشست و پاسخ را بررسی کنید.
در این مرحله، اطلاعات نشست را در گزارش عمومی یا تصاویر منتشرشده قرار ندهید؛ حتی نشستهای آزمایشگاهی نیز نباید به دیگران واگذار شوند.
مرحله سوم: بازبینی با Burp Suite
اگر از Burp Suite Community استفاده میکنید:
-
پروکسی را برای مرورگر آزمایشگاهی تنظیم کنید.
-
درخواست مربوط به سفارش ساختگی را در HTTP history پیدا کنید.
-
درخواست را به Repeater بفرستید.
-
درخواست مربوط به حساب آزمایشی A را ارسال و پاسخ را ثبت کنید.
-
فقط در محیط تحت کنترل خود، دسترسی A به منبع ساختگی B را آزمایش کنید.
-
وضعیت HTTP، محتوای پاسخ و هرگونه افشای اطلاعات را مقایسه کنید.
مستندات رسمی: راهنمای Burp Repeater.
مرحله چهارم: تحلیل نتیجه
به این موارد توجه کنید:
| مشاهده | تفسیر |
|---|---|
200 OK و داده متعلق به A |
دسترسی به منبع خود کاربر؛ طبیعی |
403 یا 404 و بدون داده خصوصی |
کنترل دسترسی احتمالاً درست عمل کرده است |
200 OK و داده خصوصی B |
احتمال IDOR؛ مالکیت و مجوز را بررسی کنید |
302 Redirect به صفحه ورود |
بهتنهایی اثبات امن بودن نیست؛ پاسخ و مسیر نهایی را بررسی کنید |
200 OK ولی فقط داده عمومی |
لزوماً IDOR نیست؛ حساسیت داده و سیاست دسترسی را بررسی کنید |
هیچ کد وضعیت HTTP بهتنهایی برای نتیجهگیری کافی نیست. گاهی سرور پاسخ موفق میدهد، اما محتوای آن عمومی است؛ گاهی هم پاسخ خطا میدهد، ولی داده حساس را در بدنه پاسخ افشا کرده است.
۷. تمرین پیشرفتهتر: IDOR در عملیات تغییر اطلاعات
IDOR فقط به مشاهده اطلاعات محدود نمیشود. ممکن است در عملیات ویرایش یا حذف نیز رخ دهد.
برای مثال، API فرضی زیر را در نظر بگیرید:
PATCH /api/profile/101
Content-Type: application/json
{
"display_name": "New Name"
}
سؤال امنیتی این است: آیا سرور بررسی میکند که پروفایل 101 متعلق به کاربر واردشده است یا خیر؟
در آزمایشگاه، برای بررسی این موضوع از دو حساب ساختگی و دادههای قابلبازنشانی استفاده کنید. معیار موفقیت تست این است که درخواست حساب A نتواند اطلاعات حساب B را تغییر دهد، مگر آنکه سیاست دسترسی صریحاً چنین اجازهای بدهد.
برای جلوگیری از آسیب ناخواسته، از آزمایش روی حساب واقعی، سفارش واقعی یا عملیات مالی اجتناب کنید. در یک آزمایشگاه آموزشی، تغییر نام نمایشی ساختگی کافی است تا منطق مجوز بررسی شود.
چکلیست آزمون دسترسی
چکلیست تست نفوذ
0 از 7
پاک کردن علامتها
این چکلیست، نتیجه آزمایش واقعی را بهجای کاربر ثبت نمیکند؛ هر مورد باید بر اساس شواهد همان آزمایشگاه علامت زده شود.
۸. علت فنی آسیبپذیری در سمت سرور
یکی از اشتباهات رایج این است که برنامه ابتدا کاربر را احراز هویت میکند و سپس سفارش را صرفاً با شناسه دریافت میکند.
نمونه منطق آسیبپذیر
کد زیر شبهکد آموزشی است:
def get_order(order_id): order = database.find_order(order_id) if order is None: return {"error": "Not found"}, 404 # اشتباه: مالکیت سفارش بررسی نشده است. return order, 200
این تابع فقط بررسی میکند که سفارش وجود دارد. اما مشخص نمیکند که کاربر فعلی حق دسترسی به آن را دارد یا خیر.
نمونه منطق امن
def get_order(current_user, order_id): order = database.find_order(order_id) if order is None: return {"error": "Not found"}, 404 if order.owner_id != current_user.id: return {"error": "Not found"}, 404 return order, 200
در این نسخه، دسترسی به سفارش به هویت کاربر فعلی وابسته است.
نکته مهم: متغیر current_user باید از نشست معتبر و احراز هویتشده سمت سرور به دست بیاید؛ نباید مالکیت را از مقداری که کاربر آزادانه در درخواست میفرستد، مانند owner_id در JSON، قبول کنیم.
روش بهتر: محدود کردن جستوجو به مالک
در بسیاری از برنامهها بهتر است رکورد از ابتدا در محدوده مجاز کاربر جستوجو شود.
نمونه SQL:
SELECT id, item, status
FROM orders
WHERE id = :order_id
AND owner_id = :authenticated_user_id;
پارامتر authenticated_user_id باید از هویت احرازشده سمت سرور تأمین شود. استفاده از پارامترهای bindشده نیز برای جلوگیری از SQL Injection ضروری است.
در برنامههای پیچیدهتر، مجوزها ممکن است به نقش کاربر، سازمان، اشتراک، وضعیت سفارش یا دسترسی مشترک وابسته باشند. بنابراین، صرف مقایسه شناسه مالک در همه برنامهها کافی نیست؛ منطق باید با سیاست واقعی دسترسی مطابقت داشته باشد.
راهنمای رسمی: OWASP Authorization Cheat Sheet.
۹. آیا استفاده از UUID مشکل را حل میکند؟
خیر. استفاده از شناسههای تصادفی و غیرقابلحدس، احتمال حدسزدن شناسه را کاهش میدهد؛ اما جایگزین کنترل دسترسی نیست.
مثلاً این شناسه:
/orders/550e8400-e29b-41d4-a716-446655440000
ممکن است بهسختی حدس زده شود، اما اگر برنامه شناسه را از یک منبع عمومی یا پاسخ API افشا کند و مجوز مالکیت را بررسی نکند، مشکل همچنان میتواند وجود داشته باشد.
به همین ترتیب، هشکردن یک شناسه ترتیبی بهتنهایی تضمین امنیت نیست. دفاع اصلی، کنترل مجوز در سمت سرور است.
۱۰. سناریوهای آزمون تکمیلی در آزمایشگاه
بعد از تمرین پایه، این سناریوها را در برنامه محلی یا آزمایشگاه آموزشی مجاز بررسی کنید.
سناریو A — شناسه در مسیر URL
بررسی کنید که دسترسی به یک منبع، علاوه بر ورود، به مجوز همان منبع وابسته باشد.
معیار قبولی: کاربر دوم نمیتواند منبع خصوصی کاربر اول را دریافت کند.
سناریو B — شناسه در JSON
بررسی کنید که سرور شناسه رکورد را از درخواست دریافت میکند، اما تصمیم مجوز را خودش میگیرد.
معیار قبولی: ارسال شناسه متعلق به حساب دیگر، مجوز اضافی ایجاد نمیکند.
سناریو C — دانلود فایل
در یک محیط ساختگی، بررسی کنید که دسترسی به فایل خصوصی با تغییر شناسه فایل ممکن نباشد.
معیار قبولی: سرور پیش از تحویل محتوا، مجوز دانلود را بررسی میکند.
سناریو D — دسترسی بین نقشها
دسترسی دو کاربر عادی و یک مدیر آزمایشگاهی را مطابق سیاست تعریفشده مقایسه کنید.
معیار قبولی: فقط نقشهایی که مجوز صریح دارند، عملیات مدیریتی را انجام میدهند.
۱۱. گزارش حرفهای آسیبپذیری
پیدا کردن یک رفتار غیرعادی پایان کار نیست. تست نفوذ حرفهای باید قابل بازتولید، مستند و قابل اصلاح باشد.
قالب پیشنهادی گزارش:
گزارش آسیبپذیری: Insecure Direct Object Reference (IDOR)
۱. خلاصه
در مسیر آزمایشگاهی [مسیر API]، کنترل مجوز دسترسی به یک منبع بهدرستی اعمال نمیشود و کاربر آزمایشی میتواند به منبعی خارج از سطح دسترسی خود دسترسی پیدا کند.
۲. دارایی و محدوده
- برنامه:
[نام برنامه آزمایشگاهی] - محیط:
[محلی / Staging مجاز] - نقطه آسیبپذیر:
[مسیر و متد HTTP] - حسابهای آزمایش:
[شناسههای ساختگی]
۳. پیششرطها
- داشتن حساب آزمایشی معتبر
- داشتن مجوز انجام آزمون در محیط تعیینشده
- وجود دو منبع ساختگی با مالکیت متفاوت
۴. مراحل بازتولید
- با حساب آزمایشی A وارد شوید.
- منبع متعلق به A را درخواست کنید و پاسخ مجاز را ثبت کنید.
- در محیط آزمایشگاهی، دسترسی به منبع متعلق به B را با همان حساب بررسی کنید.
- کد وضعیت و بدنه پاسخ را ثبت کنید.
- نتیجه را با سیاست مجوزهای مورد انتظار مقایسه کنید.
۵. نتیجه مورد انتظار
سرور باید دسترسی به منابع را بر اساس هویت و مجوز کاربر بررسی کند و داده خصوصی B را به A ندهد.
۶. نتیجه مشاهدهشده
[فقط شواهد واقعی و قابل بازتولید درج شود؛ از ثبت داده خصوصی واقعی خودداری کنید.]
۷. اثر امنیتی احتمالی
بسته به نوع منبع و سطح دسترسی، نقص میتواند موجب افشای اطلاعات، تغییر دادههای دیگر کاربران یا انجام عملیات غیرمجاز شود.
۸. راهکار اصلاح
- اعمال کنترل دسترسی سمت سرور برای هر منبع
- محدود کردن پرسوجوها به منابع مجاز کاربر
- بررسی مجوز در عملیات خواندن، ویرایش، حذف و دانلود
- افزودن آزمونهای خودکار برای جلوگیری از بازگشت آسیبپذیری
۹. وضعیت بازآزمایی
[اصلاحشده / همچنان آسیبپذیر / نیازمند بررسی بیشتر]
۱۰. شواهد
[درخواست و پاسخ پالایششده، بدون کوکی، توکن یا اطلاعات شخصی واقعی]
چگونه شدت آسیبپذیری را تعیین کنیم؟
شدت را نباید فقط بر اساس نام IDOR یا قابلحدس بودن شناسه تعیین کرد.
-
کم: منبع کماهمیت یا اطلاعات عمومی با محدودیت دسترسی اندک.
-
متوسط: افشای اطلاعات غیرعمومی یا محدود در یک حساب یا سازمان.
-
زیاد: دسترسی به اطلاعات حساس یا امکان تغییر منابع مهم دیگر کاربران.
-
بحرانی: فقط در شرایط خاص، وقتی اثر بسیار گسترده و پیامد شدید با شواهد قابل دفاع باشد.
این دستهبندی صرفاً راهنمای اولیه است. ارزیابی واقعی باید احتمال سوءاستفاده، میزان دسترسی لازم، دامنه اثر، حساسیت دادهها و پیامدهای کسبوکار را در نظر بگیرد.
۱۲. تمرین پایانی برای کاربران صفر و یک سایبر
اکنون بدون نگاه کردن به پاسخهای بالا، این چالش را حل کنید.
چالش آزمایشگاهی IDOR
وضعیت آزمایشگاه
یک API ساختگی سه سفارش دارد:
| شناسه سفارش | مالک | نوع داده |
|---|---|---|
| 501 | user_a | اطلاعات عمومی سفارش |
| 502 | user_b | اطلاعات خصوصی سفارش |
| 503 | user_a | اطلاعات خصوصی سفارش |
سیاست برنامه: هر کاربر فقط سفارشهای متعلق به خودش را میتواند مشاهده کند.
وظیفه شما
وقتی تمرین را انجام دادی، میتوانی درخواست و پاسخهای ساختگی خودت را بفرستی تا مرحلهبهمرحله بررسی کنیم.
نمایش راهنمای حل چالش
۱۳. منابع معتبر برای ادامه یادگیری
OWASP — پیشگیری از IDOR
راهنمای پیادهسازی کنترل دسترسی، محدود کردن دسترسی به منابع و جلوگیری از افشای داده.
PortSwigger Web Security Academy — تمرین تعاملی
آموزش IDOR و آزمایشگاههای کنترل دسترسی برای تمرین مرحلهبهمرحله.
MDN Web Docs — درک مفاهیم
توضیح ساده و فنی IDOR، نمونههای URL و اصول جلوگیری از دسترسی غیرمجاز.
جمعبندی: یک تست نفوذ خوب فقط تغییر دادن شناسه در URL نیست. باید مشخص کنید چه کسی درخواست را فرستاده، چه مجوزی دارد، سرور چه دادهای برگردانده، آیا دسترسی غیرمجاز واقعاً رخ داده و چگونه میتوان آن را برطرف کرد.

دیدگاه شما