کد وضعیت HTTP
یک عدد سهرقمی که توسط سرور برگردانده میشود و نتیجه یک درخواست HTTP را نشان میدهد (200=موفقیت، 404=پیدا نشد، 500=خطای سرور و غیره).
تعریف کوتاه
کدهای وضعیت پاسخهای سرور به صورت اعداد هستند: ۲۰۰ یعنی "این چیزی است که خواستی"، ۴۰۴ یعنی "نمیتوانم آن را پیدا کنم"، ۴۰۳ یعنی "اجازه نداری"، و ۵۰۰ یعنی "خراب کردم". این روشی است که سرورها سریع به شما میگویند چه اتفاقی افتاده.
تعریف کامل
کدهای وضعیت HTTP اعداد سهرقمی استانداردی هستند که نتیجه یک درخواست HTTP را نشان میدهند.
دستهبندی (بر اساس رقم اول):
۱xx - اطلاعاتی:
- ۱۰۰ Continue
- ۱۰۱ Switching Protocols
۲xx - موفقیت:
- ۲۰۰ OK (درخواست موفق)
- ۲۰۱ Created (منبع جدید ایجاد شد)
- ۲۰۴ No Content (موفقیت اما دادهای نیست)
۳xx - تغییر مسیر:
- ۳۰۱ Moved Permanently
- ۳۰۲ Found (تغییر مسیر موقت)
- ۳۰۴ Not Modified (نسخه کش همچنان معتبر است)
۴xx - خطای کلاینت:
- ۴۰۰ Bad Request (درخواست بدشکل)
- ۴۰۱ Unauthorized (نیاز به احراز هویت)
- ۴۰۳ Forbidden (احراز هویت شده اما مجاز نیست)
- ۴۰۴ Not Found (منبع وجود ندارد)
- ۴۲۹ Too Many Requests (محدودیت نرخ)
۵xx - خطای سرور:
- ۵۰۰ Internal Server Error
- ۵۰۲ Bad Gateway
- ۵۰۳ Service Unavailable
- ۵۰۴ Gateway Timeout
چرا مهم است
- تشخیص سریع مشکلات
- طراحی API و مدیریت خطا
- تجربه کاربری (صفحات خطای دوستانه)
- امنیت (نشت اطلاعات)
- SSRF نیمهکور به کدهای وضعیت متکی است
چگونه مهاجمان از آن استفاده میکنند
شناسایی SSRF نیمهکور:
حتی بدون دیدن پاسخ کامل، کدهای وضعیت اطلاعات را فاش میکنند:
1# تست شبکه داخلی2for ip in range(1, 255):3 url = f"http://192.168.1.{ip}:80"4 status = ssrf_request(url).status_code56 if status == 200:7 print(f"{ip}: سرویس فعال و پاسخگو")8 elif status == 403:9 print(f"{ip}: سرویس وجود دارد اما دسترسی ممنوع")10 elif status == timeout:11 print(f"{ip}: سرویسی نیست یا فیلتر شده")
اطلاعات به دست آمده:
- ۲۰۰/۴۰۳: میزبان وجود دارد، سرویس در حال اجراست
- ۴۰۱: احراز هویت مورد نیاز است (هدف پیدا شد)
- ۴۰۴: میزبان فعال است اما مسیر اشتباه
- Timeout: سرویسی نیست یا فایروال مسدود کرده
حملات دیگر:
شمارش مبتنی بر خطا:
1GET /api/users/123 → ۲۰۰ (کاربر وجود دارد)2GET /api/users/999 → ۴۰۴ (وجود ندارد)3→ میتوان IDهای معتبر کاربر را شمارش کرد
حملات مبتنی بر زمان:
1رمز عبور اشتباه → ۴۰۱ در ۱۰ میلیثانیه2رمز عبور صحیح → ۴۰۱ در ۱۰۰ میلیثانیه (بررسی هش)3→ شمارش نام کاربری از طریق زمان + وضعیت
چگونه تشخیص یا پیشگیری کنیم
پیشگیری:
به حداقل رساندن نشت اطلاعات:
1# بد: دلیل شکست درخواست را فاش میکند2if user_not_found:3 return 404, "کاربر وجود ندارد"4if password_wrong:5 return 401, "رمز عبور نامعتبر"67# خوب: پیام کلی8if auth_failed:9 return 401, "اعتبارنامه نامعتبر"
محدودیت نرخ:
1if too_many_requests:2 return 429, "محدودیت نرخ exceeded"
پاسخهای یکسان:
1# جلوگیری از حملات زمانی2time.sleep(random.uniform(0.1, 0.3))3return 401, "احراز هویت ناموفق"
برای SSRF:
- کدهای وضعیت خام را از درخواستهای داخلی برنگردانید
- پاسخها را قبل از نشان دادن به کاربر پالایش کنید
- کدهای وضعیت داخلی را جداگانه ثبت کنید
تشخیص:
- نظارت بر الگوهای شمارش کد وضعیت
- هشدار در مورد ۴۰۴های بیش از حد (اسکن)
- ردیابی الگوهای ۴۰۱/۴۰۳ (brute force)
- ثبت توالیهای غیرعادی کد وضعیت
باورهای غلط رایج
- "۴۰۴ یعنی سرور پایین است" - سرور فعال است، منبع پیدا نشد
- "۲۰۰ همیشه یعنی موفقیت" - منطق برنامه ممکن است شکست خورده باشد
- "۵۰۰ همیشه بد است" - به شناسایی مشکلات سرور کمک میکند
- "کدهای وضعیت اختیاری هستند" - HTTP به آنها نیاز دارد
- "کد یکسان = نتیجه یکسان" - بدنه پاسخ نیز مهم است
مثال واقعی
شمارش در GitHub از طریق کد وضعیت
1GET /username → ۴۰۴ (وجود ندارد)2GET /torvalds → ۲۰۰ (وجود دارد)
امکان شمارش همه کاربران GitHub از طریق کد وضعیت.
شمارش باکت S3 در AWS
1GET /bucket-name → ۴۰۴ (وجود ندارد)2GET /company-data → ۴۰۳ (وجود دارد اما خصوصی)3GET /public-files → ۲۰۰ (وجود دارد و قابل دسترسی)
مهاجمان از کدهای وضعیت برای پیدا کردن نام باکتهای معتبر استفاده میکنند.
SSRF نیمهکور در Capital One
اگرچه مهاجم ابتدا نمیتوانست پاسخ کامل متادیتا را ببیند، کدهای وضعیت فاش کردند:
- ۲۰۰: نقطه پایانی متادیتا وجود دارد
- ۴۰۳: احراز هویت مورد نیاز است (اما IMDSv1 به آن نیاز نداشت)
- کدهای مختلف برای مسیرهای مختلف راهنمای کاوش بودند
اصطلاحات مرتبط
HTTP Request, Server, API, Endpoint, Semi-Blind SSRF