Asosiy kontentga o‘tish

Maqolalar 10 daqiqa o‘qish 2 soat amaliyot 31 ko‘rish

SSRF: serverni o'z ichki tarmog'iga so'rov yuborishga majburlash

Serverga tashqaridan yetib bo'lmaydigan ichki xizmatlar bor — admin panel, bulut metadata, ma'lumotlar bazasi. SSRF serverning o'zini o'sha xizmatlarga so'rov yuborishga majbur qiladi. Beshta labda buni ishga tushiramiz, keyin Django'da qanday yopishni ko'ramiz.

security backend api

Mundarija

Oldingi darslarda hujum foydalanuvchining brauzeriga tegdi. Endi nishonni o'zgartiramiz: serverning o'zi. Ko'p serverlarda tashqi dunyodan ko'rinmaydigan ichki xizmatlar bor — admin panel localhost da, ma'lumotlar bazasi ichki tarmoqda, bulutda esa maxsus metadata manzili kalitlar bilan. Bularga tashqaridan yetib bo'lmaydi.

SSRF shu devorni aylanib o'tadi: agar sayt biror URL'ga o'zi so'rov yuborsa (rasm yuklash, havolani tekshirish, hisobot generatsiya qilish), siz o'sha URL'ni ichki manzilga o'zgartirasiz — va server siz uchun o'sha manzilga boradi. Devor tashqaridan mustahkam, lekin server allaqachon ichkarida.

Bu darsdan keyin siz SSRF'ni topa olasiz, uch xil filtr chetlashini tushunasiz va Django'da tashqi so'rovlarni to'g'ri cheklay olasiz.

Bu dars kimga

1-dars (Burp) tugagan bo'lsin. IP-manzil va localhost nima ekanini bilsangiz yetadi.

Buzilgan taxmin#

SSRF'ning ildizi bitta ishonchli ko'ringan taxminda:

"Server faqat men bergan, ishonchli manzillarga so'rov yuboradi."

Dasturchi funksiyani yozadi — masalan "shu URL'dagi rasmni yukla" — va URL'ni foydalanuvchi berishini o'ylamaydi, yoki o'ylasa ham "kim ham ichki manzil yozardi" deydi. Aslida:

  • Server uchun localhost — o'zi, ya'ni tashqaridan yashirin xizmatlar.
  • Server ichki tarmoqda (192.168.x.x, 10.x.x.x) — o'sha tarmoqning ichida turibdi.

  • Bulutda 169.254.169.254 — metadata xizmati, ko'pincha kalitlar bilan.

Foydalanuvchi bergan URL — matn emas, serverga beriladigan buyruq: qayerga borishni foydalanuvchi hal qiladi, server esa o'z ichki imtiyozlari bilan boradi.

Atamalar#

Atama Ma'nosi
SSRF Server-Side Request Forgery — serverni o'zi so'rov yuborishga majburlash
localhost / 127.0.0.1 mashinaning o'zi — server uchun ichki xizmatlar
internal network tashqaridan ko'rinmaydigan ichki tarmoq (192.168.x, 10.x)
cloud metadata bulut bergan maxsus manzil (169.254.169.254) — ko'pincha kalitlar
denylist (eski nomi blacklist) taqiqlangan qiymatlar ro'yxati (qolgani ruxsat)
allowlist (eski nomi whitelist) ruxsat berilgan qiymatlar ro'yxati (qolgani taqiq)
open redirect saytdagi "istalgan manzilga yo'naltiruvchi" zaiflik
SSRF filter serverga qaysi manzilga borish mumkinligini cheklovchi tekshiruv
out-of-band javob to'g'ridan qaytmaganda, tashqi kanal orqali tasdiqlash

Nazariya: server ishonchli mijoz#

Zaif qolip odatda "URL'ni oldim, so'rov yubordim" ko'rinishida:

Python
# Zaif: foydalanuvchi bergan URL'ga server to'g'ridan-to'g'ri boradi
import requests


def check_stock(request):
    url = request.POST["stockApi"]  # <-- foydalanuvchidan
    response = requests.get(url)  # <-- server o'zi boradi
    return HttpResponse(response.text)

Foydalanuvchi stockApi ga http://localhost/admin yozsa, server o'z admin paneliga boradi — chunki server uchun localhost o'zi. Tashqi foydalanuvchi hech qachon yeta olmaydigan sahifa endi ochiq.

Sxema
Tashqi hujumchi ──✗──► localhost/admin   (devor bloklaydi)
Tashqi hujumchi ─────► SAYT ─────► localhost/admin   (server ichkarida ✓)
                       "URL'ni men berdim"

Kuzating

SSRF izlaganda serverning URL, manzil yoki domen qabul qiladigan har qanday joyini qidiring — rasm yuklash havolasi, webhook manzili, "havolani tekshir" tugmasi, PDF generatsiya. O'sha qiymatni http://localhost/ ga o'zgartirib, javob o'zgarganini kuzating.

Amaliyot#

1-labServerning o'ziga#

Lab: Basic SSRF against the local server · APPRENTICE

Vazifa: http://localhost/admin ga kirib, carlos ni o'chirish.

Nimani ko'rasiz: mahsulot sahifasida "stock check" — server boshqa URL'dan zaxira sonini oladi.

Savol: stock API URL'ini o'zgartirsangiz, so'rovni kim yuboradi — sizmi yoki server? Server uchun localhost nima?

Eng oddiy tekshiruv: stockApi qiymatini http://localhost/admin ga o'zgartiring.

Bu eng toza SSRF: filtr yo'q. Server siz bergan URL'ga o'z nomidan boradi, ya'ni o'z admin paneliga. Tashqaridan localhost/admin ga yeta olmaysiz, lekin server allaqachon o'sha mashinada — siz shunchaki uni so'rov yuborishga ko'ndirdingiz.

2-labIchki tarmoqni skanerlash#

Lab: Basic SSRF against another back-end system · APPRENTICE

Vazifa: ichki tarmoqdagi (192.168.0.X) admin panelni topib, carlos ni o'chirish.

Nimani ko'rasiz: yana stock check, lekin bu safar nishon localhost emas, ichki tarmoqdagi boshqa mashina.

Savol: manzilni bilmasangiz — uni qanday topasiz? Server ichki tarmoqning ichida turibdi, ya'ni u har bir manzilni sinab ko'ra oladi.

Eng oddiy tekshiruv: 192.168.0.1 dan 192.168.0.255 gacha :8080/admin ni Burp Intruder bilan skanerlang, 200 qaytarganini toping.

Server nafaqat o'ziga, balki butun ichki tarmoqqa yeta oladi. Siz uni tarmoqni skanerlash quroliga aylantirasiz — har bir IP'ni sinab, admin panel qayerda ekanini topasiz. Bu — SSRF'ning haqiqiy kuchi: server sizga ichki tarmoqqa "deraza" ochib beradi.

3-labDenylist'ni aldash#

Lab: SSRF with blacklist-based input filter · PRACTITIONER

Vazifa: yana localhost/admin, lekin server localhost va admin so'zlarini bloklaydi.

Nimani ko'rasiz: filtr qo'shilgan — 127.0.0.1 va localhost rad etiladi.

Savol: localhost ni yozmasdan, o'sha manzilga boshqacha yo'l yo'qmi? Bitta IP'ni necha xil yozish mumkin?

Eng oddiy tekshiruv: http://127.1/ (qisqartirilgan IP) sinang; admin ni ikki marta URL-kodlang (%2561dmin).

Denylist — sanashga urinish, va sanash doim to'liq emas. localhost ni 127.1, 127.0.0.1 ni 0, 2130706433 (o'nlik shakl), [::1] (IPv6) — bir manzilning o'nlab yozuvi bor. Filtr admin so'zini bloklasa, uni kodlab yuborasiz. Nimani taqiqlashni sanaganingizda, doim bittasini unutasiz.

4-labAllowlist'ni aldash#

Lab: SSRF with whitelist-based input filter · PRACTITIONER

Vazifa: yana localhost/admin, lekin bu safar server faqat o'z domenini ruxsat etadi.

Nimani ko'rasiz: allowlist — URL faqat kutilgan domendan bo'lishi shart. Denylist'dan kuchliroq.

Savol: URL'ning qaysi qismini server "domen" deb o'qiydi? URL sintaksisida domenga o'xshab, aslida boshqa joyga boradigan qism bormi?

Eng oddiy tekshiruv: https://kutilgan-domen@localhost/admin — @ belgisidan oldingi qism foydalanuvchi nomi, keyingisi haqiqiy nishon.

Allowlist kuchliroq, lekin u ham URL'ni qanday o'qishga bog'liq. URL sintaksisi murakkab: @ belgisi, # fragment, kodlangan belgilar — server URL'ni bir xil, filtr boshqacha o'qishi mumkin. Bu farq — teshik. Yechim URL'ni "tekshirish" emas, uni parse qilib, komponentlarini solishtirishda.

5-labOpen redirect orqali#

Lab: SSRF with filter bypass via open redirection vulnerability · PRACTITIONER

Vazifa: http://192.168.0.12:8080/admin ga yetish, lekin filtr faqat o'z domenini ruxsat etadi.

Nimani ko'rasiz: SSRF filtri qattiq, lekin saytda "istalgan manzilga yo'naltiruvchi" (open redirect) sahifa bor.

Savol: server faqat o'z domeniga boradi. Lekin o'sha domendagi sahifa uni boshqa joyga yo'naltirsa, server yo'naltirishga ergashadimi?

Eng oddiy tekshiruv: ruxsat etilgan URL'ni open redirect'ga yo'naltiring, u esa ichki manzilga olib borsin.

Bu labning saboqi ikki qismli. Birinchi: zaifliklar birlashadi — o'zicha zararsiz open redirect SSRF filtrini teshib o'tadi. Ikkinchi: server yo'naltirishga ergashsa, filtr faqat birinchi manzilni tekshiradi, oxirgisini emas. Ishonchli domenga yuborilgan so'rov ishonchsiz joyga tushib qoladi.

Nima ishlamaydi va nega#

"localhost va 127.0.0.1 ni bloklasam yetadi." 3-lab: bitta manzilning o'nlab yozuvi bor — 127.1, 0, 2130706433, [::1]. Qora ro'yxat hech qachon to'liq emas.

"Faqat o'z domenimni ruxsat etaman." 4-lab: URL'ni tekshirish qiyin — @, #, kodlash server bilan filtrni turlicha o'qitadi. 5-lab: o'z domeningizdagi redirect sizni ichkariga olib kiradi.

"Javob qaytmasa, SSRF xavfsiz." Javob ko'rinmasa ham (blind SSRF), server borgani out-of-band kanal bilan tasdiqlanadi va ichki ta'sir (o'chirish, ishga tushirish) baribir bo'ladi.

Endi yopamiz#

SSRF'ni "URL'ni tekshirish" bilan to'liq yopib bo'lmaydi — 4 va 5-lab buni ko'rsatdi. To'g'ri yechim bir necha qatlam:

1. Allowlist, domen emas — to'liq URL parse qilib. Foydalanuvchi faqat tanlaydi, URL'ni o'zi yozmaydi:

Python
# Zaif: URL foydalanuvchidan, tekshiruv matn darajasida
url = request.POST["stockApi"]
if "localhost" not in url:  # <-- yengil aldanadi
    requests.get(url)

# To'g'riroq: foydalanuvchi ID tanlaydi, URL'ni server yasaydi
supplier = get_object_or_404(Supplier, pk=request.POST["supplier_id"])
requests.get(supplier.stock_url)  # <-- URL ishonchli manbadan

2. Server so'rovlarini tarmoq darajasida cheklang. Ilova ichki manzillarga (127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, 169.254.0.0/16) umuman bora olmasin — buni firewall yoki chiquvchi proksida qo'ying, ilova kodiga tayanmang.

3. Yo'naltirishlarga ergashmang yoki har qadamni qayta tekshiring:

Python
# Yo'naltirishni o'chirish: server oxirgi manzilga jimgina o'tib ketmasin
requests.get(url, allow_redirects=False, timeout=5)

Muhim

eng ishonchli himoya — foydalanuvchidan URL umuman olmaslik. Agar tashqi manzilga so'rov kerak bo'lsa, foydalanuvchi ro'yxatdan tanlaydi, URL'ni server o'zi biladi. "Foydalanuvchi bergan URL'ni tozalab ishlataman" — deyarli har doim yengiladigan yo'l.

Aniq misol: bu sayt tashqariga so'rov yuboradigan ikki joyi bor — GitHub repo sonini olish (github.py) va Telegram'ga e'lon (announce.py). Ikkalasida ham manzil qat'iy — GitHub API va Telegram API'ning o'zgarmas https hosti, foydalanuvchi URL bermaydi (kodda # noqa: S310 (fixed https host) izohi shuni belgilaydi). Ya'ni SSRF uchun asosiy shart — foydalanuvchi boshqaradigan URL — bu yerda umuman yo'q. Eng yaxshi himoya aynan shu: URL'ni foydalanuvchidan olmaslik.

Nazorat savollari#

  1. SSRF nima uchun ishlaydi? Server uchun localhost nimani anglatadi?
  2. Nega tashqi hujumchi localhost/admin ga yeta olmaydi, server esa yeta oladi?
  3. 2-labda serverni nimaga aylantirdingiz? "Ichki tarmoqqa deraza" nima degani?
  4. Bitta IP-manzilni necha xil yozish mumkin? Bu denylist'ni nega yiqitadi (3-lab)?
  5. Allowlist denylist'dan kuchliroq. Uni nega baribir aldash mumkin (4-lab)?
  6. Open redirect o'zicha zararsiz. U SSRF bilan qanday birlashadi (5-lab)?
  7. cloud metadata manzili (169.254.169.254) nega SSRF uchun eng xavfli nishon?
  8. Nega SSRF'ni faqat ilova kodida tuzatish yetarli emas? Tarmoq darajasi nima beradi?
  9. allow_redirects=False nimadan himoya qiladi?
  10. Eng ishonchli yechim nima — nega "URL'ni tozalash" emas?

Report uchun talablar#

  1. Skrinshot: kamida bitta labda admin panel yoki "solved" ko'ringan holat.
  2. Skanerlash: 2-labda ichki manzilni qanday topdingiz? Burp Intruder sozlamangizni tushuntiring.
  3. Filtr sindi: 3, 4 yoki 5-labda filtrni qanday aldadingiz? Kamida bittasini o'z so'zingiz bilan yozing.
  4. Tuzatuvchi kod: tasavvuriy (yoki o'z loyihangizdan) tashqi URL qabul qiladigan view oling. Uni yuqoridagi uch qatlamdan kamida ikkitasi bilan yoping. Oldingi va keyingi holatni keltiring.

Faqat ruxsat berilgan joyda

SSRF ichki tizimlarga, bulut kalitlariga yetishi mumkin — natijasi og'ir. Uni faqat PortSwigger laboratoriyasida yoki o'zingizga tegishli tizimda sinang. Birovning serverini ichki tarmog'iga so'rov yuborishga majburlash — jinoyat.


Keyingi dars: SQL injection — foydalanuvchi kiritgan matn bazaga buyruq bo'lib tushganda, va nega parametrlangan so'rov yagona to'g'ri yechim.

10 daqiqa 31 marta o‘qildi