آموزش عملی SSRF از صفر تا پیشرفته در آزمایشگاه ایزوله

Practical SSRF Training From Zero to Advanced in an Isolated Lab
0 دیدگاه
۱۴۰۵-۰۷-۲۹ ۱۷:۳۸:۳۳

در این آموزش یاد می‌گیریم آسیب‌پذیری SSRF (Server-Side Request Forgery) چیست، چگونه در یک آزمایشگاه ایزوله آن را شناسایی و به‌صورت کنترل‌شده بازتولید کنیم، نتایج را تحلیل کنیم و در نهایت راهکارهای اصولی رفع آن را پیاده‌سازی کنیم.

تمام تمرین‌ها برای محیط محلی و تحت کنترل طراحی شده‌اند؛ هدف، درک رفتار سرور آسیب‌پذیر است، نه دسترسی به سامانه‌های واقعی یا اطلاعات محرمانه.

۱. SSRF چیست و چرا خطرناک است؟

SSRF PortSwigger Academy (Lab 1 solution) | by Ammar Ahmed | Dec, 2025 | Medium

What Is Server-Side Request Forgery? | Akamai

Server-side request forgery (SSRF) | by Errorfiathck | Medium

SSRF زمانی رخ می‌دهد که یک برنامه وب، آدرسی را از کاربر دریافت کند و بدون اعتبارسنجی و محدودیت مناسب، از سمت سرور به آن آدرس درخواست بفرستد.

برای مثال، تصور کن سایتی قابلیتی برای دریافت تصویر از طریق URL دارد. کاربر آدرس تصویر را وارد می‌کند و سرور آن را دانلود می‌کند. اگر برنامه هر URL دلخواهی را بپذیرد، ممکن است درخواست‌هایی را به مقصدهایی بفرستد که از بیرون قابل دسترسی نیستند.

چرخه وقوع آسیب‌پذیری

۱. ورودی کاربر

یک URL به برنامه ارسال می‌شود.

۲. پردازش سمت سرور

برنامه بدون کنترل کافی، درخواست خروجی می‌سازد.

۳. دسترسی ناخواسته

سرور ممکن است به یک مقصد داخلی یا غیرمجاز درخواست بفرستد.

پیامدهای احتمالی SSRF شامل دسترسی به سرویس‌های داخلی، افشای اطلاعات قابل دسترس برای سرور و سوءاستفاده از دسترسی شبکه‌ای برنامه است. شدت آسیب‌پذیری به معماری، سطح دسترسی سرور و کنترل‌های شبکه بستگی دارد.

۲. آماده‌سازی آزمایشگاه ایزوله

برای این تمرین از Kali Linux و یک برنامه آزمایشی محلی استفاده می‌کنیم. آزمایشگاه باید به‌گونه‌ای تنظیم شود که هیچ درخواست آزمایشی به شبکه عمومی یا سرویس‌های واقعی ارسال نشود.

پیشنهاد معماری:

  • سیستم عامل: Kali Linux

  • برنامه هدف: یک برنامه آزمایشی آسیب‌پذیر که خودمان کنترل می‌کنیم

  • سرویس مقصد: یک HTTP server محلی با پاسخ ساختگی

  • شبکه: شبکه داخلی ماشین مجازی، بدون اتصال خروجی به اینترنت

  • داده‌ها: فقط اطلاعات ساختگی و غیرحساس

اگر از Docker یا ماشین مجازی استفاده می‌کنی، محدودسازی شبکه را پیش از اجرای برنامه انجام بده. صرفاً اجرا کردن برنامه روی localhost تضمین نمی‌کند که تمام مسیرهای شبکه آن ایزوله باشند.

۳. ساخت سرویس داخلی ساختگی

ابتدا یک سرویس داخلی ایجاد می‌کنیم که فقط پیام آزمایشی برگرداند. این سرویس هیچ اطلاعات واقعی یا محرمانه‌ای ندارد.

در ترمینال Kali Linux:

mkdir ssrf-lab
cd ssrf-lab

python3 -m venv .venv
source .venv/bin/activate

pip install flask requests

فایل mock_service.py را بساز:

from flask import Flask, jsonifyapp = Flask(__name__)@app.get("/status")def status():    return jsonify({        "service": "internal-lab",        "status": "ok",        "message": "SSRF training lab"    })if __name__ == "__main__":    app.run(host="127.0.0.1", port=8001, debug=False)

سرویس را در ترمینال اول اجرا کن:

python mock_service.py

خروجی مورد انتظار، اجرای سرویس روی پورت 8001 است. برای بررسی مستقیم آن، در ترمینال دوم اجرا کن:

curl http://127.0.0.1:8001/status

پاسخ مورد انتظار:

{
  "message": "SSRF training lab",
  "service": "internal-lab",
  "status": "ok"
}

این سرویس نقش یک مقصد داخلی ساختگی را دارد؛ در این مرحله هنوز آسیب‌پذیری SSRF را آزمایش نکرده‌ایم.

۴. ساخت برنامه وب آزمایشی

اکنون برنامه‌ای می‌سازیم که قابلیت دریافت URL و درخواست‌دادن از سمت سرور را داشته باشد. برای جلوگیری از تبدیل‌شدن تمرین به ابزاری برای دسترسی به مقصدهای دلخواه، برنامه فقط به سرویس آزمایشگاهی مشخص‌شده اجازه درخواست می‌دهد.

فایل app.py:

from flask import Flask, request, jsonifyfrom urllib.parse import urlparseimport requestsapp = Flask(__name__)LAB_HOST = "127.0.0.1"LAB_PORT = 8001@app.get("/")def index():    return """    <h2>SSRF Security Lab</h2>    <form action="/fetch" method="get">      <input        name="url"        value="http://127.0.0.1:8001/status"        style="width:350px"      >      <button type="submit">Send request</button>    </form>    """@app.get("/fetch")def fetch_url():    url = request.args.get("url", "")    parsed = urlparse(url)    if (        parsed.scheme != "http"        or parsed.hostname != LAB_HOST        or parsed.port != LAB_PORT        or parsed.username is not None        or parsed.password is not None    ):        return jsonify({            "error": "Destination not allowed"        }), 403    try:        response = requests.get(            url,            timeout=3,            allow_redirects=False        )        return jsonify({            "upstream_status": response.status_code,            "upstream_body": response.text        })    except requests.RequestException:        return jsonify({            "error": "Lab service unavailable"        }), 502if __name__ == "__main__":    app.run(        host="127.0.0.1",        port=5000,        debug=False    )

در ترمینال دوم، از پوشه ssrf-lab برنامه را اجرا کن:

python app.py

مرورگر را باز کن و به این آدرس برو:

http://127.0.0.1:5000/

سپس روی دکمه ارسال درخواست کلیک کن.

چه اتفاقی افتاد؟

  1. مرورگر درخواست را به برنامه روی پورت 5000 فرستاد.

  2. برنامه خودش به سرویس ساختگی روی پورت 8001 درخواست داد.

  3. پاسخ سرویس داخلی از طریق برنامه به مرورگر برگشت.

این رفتار، مسیر اصلی SSRF را نشان می‌دهد: درخواست دوم را سرور برنامه می‌فرستد، نه مرورگر کاربر.

نکته مهم: کد بالا نمونه‌ای از یک واسط درخواست محدودشده است، نه نمونه‌ای از SSRF کاملاً آسیب‌پذیر؛ محدودیت مقصد عمداً برای حفظ ایمنی آزمایشگاه اعمال شده است.

۵. سناریوی عملی: شناسایی و تحلیل SSRF

در این مرحله چند آزمایش کنترل‌شده اجرا می‌کنیم تا تفاوت میان درخواست مجاز و مقصد غیرمجاز را مشاهده کنیم.

میز آزمایش SSRF

هر سناریو را انتخاب کن و ورودی، نتیجه مورد انتظار و تحلیل آن را ببین.

1. درخواست مجاز به سرویس آزمایشگاه2. مقصد با پورت متفاوت3. استفاده از HTTPS4. آدرس دامنه عمومی

ورودی آزمایشی

http://127.0.0.1:8001/status

کپی ورودی

نتیجه مورد انتظار

200 و پاسخ ساختگی سرویس

تحلیل امنیتی

برنامه توانسته از سمت سرور درخواست بفرستد.

این نتایج بر اساس کدی که در بخش قبل ساختیم پیش‌بینی شده‌اند؛ نتیجه واقعی باید با اجرای برنامه بررسی شود. این رابط صرفاً سناریوها را نمایش می‌دهد و درخواست شبکه ارسال نمی‌کند.

۶. چگونه SSRF واقعی را در یک تست نفوذ مجاز تشخیص دهیم؟

در یک ارزیابی امنیتی، وجود پارامتر URL به‌تنهایی اثبات آسیب‌پذیری نیست. باید مشخص شود آیا سرور واقعاً درخواست خروجی را به مقصد تحت کنترل آزمایش می‌فرستد یا خیر.

نشانه‌های قابل بررسی:

  • ورودی قابل‌کنترل: برنامه URL را از کاربر دریافت می‌کند.

  • درخواست سمت سرور: لاگ سرویس آزمایشگاهی نشان می‌دهد که درخواست از طرف برنامه ارسال شده است.

  • تأثیر ورودی بر مقصد: تغییر URL در محدوده آزمایشگاه، مقصد درخواست را تغییر می‌دهد.

  • کنترل دسترسی ناکافی: برنامه مقصدها را به شکل قابل اتکا محدود نمی‌کند.

  • شواهد قابل تکرار: نتیجه در چند اجرای مستقل و بدون دسترسی به داده واقعی قابل بازتولید است.

ابزارهایی مانند Burp Suite می‌توانند برای مشاهده و اصلاح درخواست HTTP و مقایسه پاسخ‌ها در همین محیط محلی استفاده شوند.

۷. راهکارهای جلوگیری از SSRF

مهم‌ترین نکته این است که اعتبارسنجی ساده رشته URL به‌تنهایی کافی نیست. کنترل باید در سطح مقصد، شبکه و نحوه ارسال درخواست انجام شود.

کنترل امنیتی اقدام پیشنهادی
Allowlist مقصد فقط دامنه‌ها و پورت‌های ضروری را مجاز کن.
اعتبارسنجی URL طرح، میزبان، پورت و اجزای غیرمجاز را بررسی کن.
کنترل DNS و IP آدرس نهایی را بررسی کن و خطر تغییر پاسخ DNS را در نظر بگیر.
جلوگیری از Redirect تغییر مسیر به مقصد تأییدنشده را غیرفعال یا مجدداً اعتبارسنجی کن.
محدودیت شبکه ارتباط خروجی سرور را با Firewall و سیاست‌های شبکه محدود کن.
کنترل پاسخ اندازه پاسخ، زمان انتظار و نوع محتوا را محدود کن.
حفاظت از سرویس‌های داخلی احراز هویت و کنترل دسترسی را مستقل از شبکه اعمال کن.

نکته پیشرفته: اگر برنامه به دامنه‌های مجاز نیاز دارد، بررسی اولیه URL کافی نیست. باید IP مقصد پس از حل DNS بررسی شود، اتصال به همان مقصد تأییدشده متصل بماند و مسیرهای تغییر مسیر نیز کنترل شوند؛ در غیر این صورت خطر DNS rebinding یا دورزدن اعتبارسنجی وجود دارد.

۸. چک‌لیست پایان آزمایشگاه

0 از ۶ مرحله تکمیل شده

شروع مجدد

جمع‌بندی

SSRF یکی از آسیب‌پذیری‌های مهم برنامه‌های وب است؛ زیرا می‌تواند دسترسی شبکه‌ای سرور را در اختیار ورودی کنترل‌شده کاربر قرار دهد. برای اثبات آن، باید مسیر درخواست سمت سرور را با شواهد آزمایشگاهی نشان داد، محدودیت‌ها را ارزیابی کرد و سپس اصلاحات را آزمود.

دسته بندی‌ها:

دیدگاه شما

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *