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.
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:
# 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.
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:
# 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:
# 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#
- SSRF nima uchun ishlaydi? Server uchun
localhostnimani anglatadi? - Nega tashqi hujumchi
localhost/adminga yeta olmaydi, server esa yeta oladi? - 2-labda serverni nimaga aylantirdingiz? "Ichki tarmoqqa deraza" nima degani?
- Bitta IP-manzilni necha xil yozish mumkin? Bu denylist'ni nega yiqitadi (3-lab)?
- Allowlist denylist'dan kuchliroq. Uni nega baribir aldash mumkin (4-lab)?
- Open redirect o'zicha zararsiz. U SSRF bilan qanday birlashadi (5-lab)?
cloud metadatamanzili (169.254.169.254) nega SSRF uchun eng xavfli nishon?- Nega SSRF'ni faqat ilova kodida tuzatish yetarli emas? Tarmoq darajasi nima beradi?
allow_redirects=Falsenimadan himoya qiladi?- Eng ishonchli yechim nima — nega "URL'ni tozalash" emas?
Report uchun talablar#
- Skrinshot: kamida bitta labda admin panel yoki "solved" ko'ringan holat.
- Skanerlash: 2-labda ichki manzilni qanday topdingiz? Burp Intruder sozlamangizni tushuntiring.
- Filtr sindi: 3, 4 yoki 5-labda filtrni qanday aldadingiz? Kamida bittasini o'z so'zingiz bilan yozing.
- 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.