Asosiy kontentga o‘tish

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

CSRF: brauzer sizning nomingizdan, siz bilmagan holda so'rov yuboradi

Boshqa saytdagi bitta rasm sizning bankingizga so'rov yuborishi mumkin — va cookie o'zi qo'shiladi. Sabab: brauzer cookie'ni kim so'raganidan qat'i nazar biriktiradi. Beshta labda hujumni quramiz, keyin uni token va SameSite bilan yopamiz.

security backend api

Mundarija

Oldingi darsda begona kodni boshqalarning brauzeriga tushirdik. Endi undan ham qiziq narsa qilamiz: begona kodsiz, faqat bitta oddiy forma bilan qurbonning nomidan haqiqiy so'rov yuboramiz — parolini o'zgartirish, pulini o'tkazish, emailini almashtirish.

Buning kaliti bitta faktda: brauzer cookie'ni kim so'raganiga qaramay biriktiradi. Siz zararli saytda turgan bo'lsangiz ham, u sizning bank saytingizga so'rov yuborsa, brauzer bank cookie'sini o'zi qo'shib yuboradi. Server esa cookie'ni ko'radi va "bu o'sha foydalanuvchi" deb o'ylaydi.

Bu darsdan keyin siz CSRF hujumini qura olasiz, uni to'xtatadigan uch qatlamni (token, SameSite, Referer) tushunasiz va Django'da uni to'g'ri yopa olasiz.

Bu dars kimga

1-dars (Burp) tugagan bo'lsin. HTML forma nima ekanini bilsangiz yetadi. Bu labllar PortSwigger'ning "exploit server"idan foydalanadi.

Buzilgan taxmin#

CSRF'ning ildizi bitta xato tenglamada:

"So'rov cookie bilan keldi. Demak, uni foydalanuvchining o'zi yubordi."

Bu ikki xil narsani chalkashtiradi:

  • Autentifikatsiya — so'rov cookie bilan keldimi? (kim yubordi)
  • Niyat — foydalanuvchi bu so'rovni chindan xohladimi? (nega yubordi)

Cookie birinchisiga javob beradi, ikkinchisiga emas. Brauzer cookie'ni avtomatik biriktiradi — foydalanuvchi tugmani bosdimi yoki begona sahifadagi yashirin forma o'zi yubordimi, cookie baribir qo'shiladi. Server ikkalasini ajrata olmaydi, chunki ikkalasi bir xil ko'rinadi.

CSRF aynan shu bo'shliqdan foydalanadi: haqiqiy foydalanuvchining haqiqiy cookie'si bilan, lekin uning irodasisiz yuborilgan so'rov.

Atamalar#

Atama Ma'nosi
CSRF Cross-Site Request Forgery — qurbon nomidan uning bilmasidan so'rov yuborish
exploit server PortSwigger bergan sayt: hujum HTML'ini joylab, qurbonga yuborasiz
CSRF token formaga qo'yiladigan, taxmin qilib bo'lmaydigan maxfiy qiymat
SameSite cookie'ning atributi: cookie boshqa saytdan kelgan so'rovga qo'shilsinmi
SameSite=Strict boshqa saytdan kelgan hech qanday so'rovga cookie qo'shilmaydi
SameSite=Lax faqat yuqori darajali GET navigatsiyaga qo'shiladi (Django default)
Referer so'rov qaysi sahifadan kelganini ko'rsatuvchi sarlavha
state-changing request holatni o'zgartiruvchi so'rov (parol, email, pul) — himoya shularga kerak
pre-flight brauzer avval ruxsat so'raydigan tekshiruv (murakkab so'rovlar uchun)

Zaif holatni tasavvur qiling: bank saytida emailni o'zgartirish oddiy POST forma orqali, va server faqat cookie'ni tekshiradi.

Python
# Zaif: faqat sessiya tekshiriladi, so'rov qayerdan kelgani emas
@login_required
def change_email(request):
    request.user.email = request.POST["email"]
    request.user.save()
    return redirect("account")

Endi hujumchi o'z saytiga shunday forma qo'yadi:

Sxema
Hujumchi sahifasi                          Bank serveri
─────────────────                          ────────────
<form action="bank.com/change-email"
      method="POST">
  <input name="email"
         value="hacker@evil.com">
</form>
<script>form.submit()</script>  ─────────►  cookie AVTOMATIK qo'shiladi
                                            server: "bu o'sha user" ✓
                                            email o'zgardi ✗

Qurbon shunchaki hujumchi sahifasini ochadi — forma o'zini yuboradi, brauzer bank cookie'sini qo'shadi, email o'zgaradi. Qurbon hech nima bosmadi.

Kuzating

CSRF faqat holatni o'zgartiruvchi so'rovlarga tegishli. Ma'lumot o'qish (GET) CSRF bilan o'g'irlanmaydi — javob hujumchiga qaytmaydi. Xavf — email/parol/pul o'zgartiradigan POST larda.

Amaliyot#

1-labHech qanday himoya yo'q#

Lab: CSRF vulnerability with no defenses · APPRENTICE

Vazifa: qurbon emailini o'zgartiruvchi HTML yasab, exploit serverga joylash.

Nimani ko'rasiz: email o'zgartirish formasi, hech qanday token yo'q.

Savol: forma faqat email maydonini yuboradi. Xuddi shu formani o'z saytingizda yasasangiz, cookie'ni kim qo'shadi?

Eng oddiy tekshiruv: Burp'da so'rovni oling, "Copy to CSRF PoC" bilan HTML yasang (yoki qo'lda forma yozing), exploit serverga qo'ying.

Bu eng toza CSRF: himoya umuman yo'q. Sizning HTML formangiz bank serveriga POST yuboradi, brauzer cookie'ni o'zi qo'shadi, server farqni sezmaydi. Butun hujum bitta formadan iborat — JavaScript ham shart emas, <img> yoki avtomatik yuboriladigan forma yetadi.

2-labToken faqat POST'da tekshiriladi#

Lab: CSRF where token validation depends on request method · APPRENTICE

Vazifa: yana emailni o'zgartirish, lekin bu safar token bor.

Nimani ko'rasiz: forma CSRF token bilan keladi va POST da u tekshiriladi.

Savol: token POST da tekshiriladi. Xuddi shu amalni GET bilan yuborsangiz, token tekshiriladimi?

Eng oddiy tekshiruv: so'rovni POST dan GET ga o'zgartiring va tokenni umuman olib tashlang.

IDOR darsidagi 5-labni eslang — u yerda ham tekshiruv HTTP metodiga bog'lab qo'yilgan edi. Bu yerda ham xuddi shu xato: himoya bor, lekin u faqat bitta metodda ishlaydi. Server GET da tokenni tekshirmaydi, ya'ni GET bilan kelgan hujum yamoqni butunlay chetlab o'tadi.

3-labToken sessiyaga bog'lanmagan#

Lab: CSRF where token is not tied to user session · PRACTITIONER

Vazifa: emailni o'zgartirish, token bor va POST da tekshiriladi.

Nimani ko'rasiz: server token haqiqiyligini tekshiradi, lekin u tokenning kimga tegishliligini tekshirmaydi.

Savol: o'zingiz uchun haqiqiy token olsangiz va uni qurbonning so'roviga qo'ysangiz — server uni qabul qiladimi?

Eng oddiy tekshiruv: o'z hisobingizdan token oling, hujum formasiga o'sha tokenni qo'ying.

Token bor, lekin u egasiz. Server "bu token haqiqiymi" deb so'raydi, "bu token shu foydalanuvchiniki mi" deb so'ramaydi — xuddi IDOR'dagi kabi. Hujumchi o'z tokenini oladi va qurbonga taqadi. Token maxfiy bo'lgani yetmaydi; u sessiyaga bog'langan bo'lishi shart.

4-labSameSite chetlab o'tiladi#

Lab: SameSite Strict bypass via client-side redirect · PRACTITIONER

Vazifa: emailni o'zgartirish, cookie SameSite=Strict bilan himoyalangan.

Nimani ko'rasiz: SameSite=Strict boshqa saytdan kelgan so'rovga cookie'ni qo'shmaydi — hujum to'g'ridan-to'g'ri ishlamaydi.

Savol: boshqa saytdan to'g'ridan yuborolmasangiz — saytning o'z ichidagi biror sahifa sizni kerakli manzilga yo'naltirib yuborolmaydimi?

Eng oddiy tekshiruv: saytdagi client-side redirect'ni toping, hujumni o'sha orqali "sayt ichidan" kelgandek qiling.

SameSite=Strict kuchli himoya, lekin u ham mutlaq emas. Agar saytning o'zida boshqariladigan yo'naltirish (redirect) bo'lsa, hujum "sayt ichida" kelgandek ko'rinadi va cookie qo'shiladi. Bitta himoya qatlamiga tayanish xatarli — shuning uchun token va SameSite birga ishlatiladi.

5-labReferer bo'lmasa o'tadi#

Lab: CSRF where Referer validation depends on header being present · PRACTITIONER

Vazifa: emailni o'zgartirish, server Referer sarlavhasini tekshiradi.

Nimani ko'rasiz: server so'rov qayerdan kelganini Referer bilan tekshiradi — begona saytdan kelgan so'rovni rad etadi.

Savol: server Referer bor bo'lsa tekshiradi. Uni umuman yubormasangiz nima bo'ladi?

Eng oddiy tekshiruv: hujum sahifasiga Referer yuborishni to'xtatuvchi meta-teg qo'ying va so'rovni Referer'siz yuboring.

Bu yerda tekshiruv shartli: "Referer bo'lsa — tekshir". Hujumchi Referer'ni umuman yubormaydi va shart bajarilmaydi. Umumiy qoida: himoya "agar X bo'lsa tekshir" ko'rinishida bo'lsa, hujumchi X'ni yo'q qiladi. Referer o'zi ham ishonchsiz — u yo'qolishi, o'zgarishi mumkin; shuning uchun u birlamchi himoya emas.

Nima ishlamaydi va nega#

"Formani POST qilsam yetadi." GET bilan o'g'irlab bo'lmaydi degan o'ylash xato — server GET da ham amalni bajarsa (2-lab), hujum GET bilan o'tadi. Metod himoya emas.

"Tokenni tekshiryapman-ku." 2 va 3-lab shuni yiqitdi: token har metodda tekshirilishi va sessiyaga bog'langan bo'lishi shart. Bittasi yetishmasa, token bor-yo'g'i bezak.

"Referer ni tekshiraman." 5-lab: Referer yo'qolishi mumkin, hujumchi uni ataylab yo'qotadi. Referer — qo'shimcha ishora, birlamchi himoya emas.

Endi yopamiz#

Yaxshi xabar: Django CSRF himoyasini qutidan chiqib beradi. Kerak bo'lgani — uni o'chirmaslik.

Python
# settings.py — bu middleware standart holatda yoqilgan, o'chirmang
MIDDLEWARE = [
    # ...
    "django.middleware.csrf.CsrfViewMiddleware",
]
Django/Jinja
{# Har state-changing formaga {% csrf_token %} qo'shiladi — token sessiyaga bog'langan #}
<form method="post" action="/change-email/">
  {% csrf_token %}
  <input type="email" name="email">
  <button>Saqlash</button>
</form>

Django tokeni sessiyaga bog'langan (3-lab avtomatik yopiladi) va har POST/PUT/DELETE da tekshiriladi (2-lab yopiladi). Cookie esa default SameSite=Lax bilan keladi — bu ikkinchi qatlam (4-labning bir qismi).

Muhim

@csrf_exempt — eng xavfli dekorator. U CSRF himoyasini o'chiradi. Uni faqat token o'rniga boshqa himoyasi bor endpoint'ga (masalan imzolangan webhook) qo'ying, "ishlamayapti" muammosini "yechish" uchun emas.

API uchun. Token forma bilan kelmaydigan JSON API'da CSRF boshqacha hal qilinadi: agar autentifikatsiya cookie orqali bo'lsa — token baribir kerak; agar Authorization: Bearer ... sarlavhasi orqali bo'lsa — CSRF umuman qo'llanmaydi, chunki brauzer bu sarlavhani avtomatik qo'shmaydi. Bu sayt cookie-sessiya ishlatadi, shuning uchun layk kabi POST lar CSRF token bilan yuboriladi. Mana shu saytning layk formasi ([templates/writing/_like.html]):

Django/Jinja
{# Layk POST'i — JavaScript fon'da yuboradi, lekin token baribir formada #}
<form method="post" action="{{ like_url }}?partial=1" data-like class="contents">
  {% csrf_token %}
  ...
</form>

{% csrf_token %} yashirin maydon qo'yadi, CsrfViewMiddleware ([config/settings/base.py] dagi MIDDLEWARE ro'yxatida) har POST da uni tekshiradi. Layk anonim (login yo'q), lekin CSRF himoyasi baribir bor — chunki u sessiya cookie'siga tayanadi, va aynan shuni CSRF ishlatadi.

Nazorat savollari#

  1. CSRF nima uchun ishlaydi? "Cookie o'zi qo'shiladi" nimani anglatadi?
  2. Autentifikatsiya va niyat orasidagi farq nima? CSRF qaysi bo'shliqdan foydalanadi?
  3. CSRF faqat POST da bo'ladimi? 2-lab misolida tushuntiring.
  4. Token bor, lekin sessiyaga bog'lanmagan bo'lsa nima bo'ladi (3-lab)?
  5. SameSite=Strict CSRF'ni butunlay to'xtatadimi? 4-lab nimani ko'rsatdi?
  6. Nega Referer tekshiruvi birlamchi himoya bo'la olmaydi (5-lab)?
  7. Django'da {% csrf_token %} qanday himoya beradi? U ikki labni bir yo'la yopadi — qaysilarini?
  8. @csrf_exempt nima qiladi va u qachon o'rinli?
  9. Authorization: Bearer sarlavhasi bilan ishlaydigan API'ga nega CSRF token kerak emas?
  10. Nega bitta himoya (faqat token, yoki faqat SameSite) yetarli emas?

Report uchun talablar#

  1. Skrinshot: kamida bitta labda "Congratulations, you solved the lab" ko'ringan holat.
  2. Hujum HTML'i: 1-labda yasagan formangizni keltiring va qaysi qismi cookie'ni "o'zi qo'shdirganini" tushuntiring.
  3. Yamoq sindi: 2, 3, 4 yoki 5-labda himoya qanday chetlab o'tildi? Kamida bittasini o'z so'zingiz bilan yozing.
  4. Tuzatuvchi kod: o'z loyihangizdan (yoki tasavvuriy) state-changing forma yoki view oling, unda CSRF himoyasi bo'lmasin, va uni {% csrf_token %} / CsrfViewMiddleware bilan yoping. Oldingi va keyingi holatni keltiring.

Faqat ruxsat berilgan joyda

CSRF hujumi haqiqiy pul o'tkazishi yoki hisob egallashi mumkin. Uni faqat PortSwigger laboratoriyasida yoki o'zingizga tegishli saytda sinang. Birovning nomidan so'rov yuborish — natijasi qanday bo'lishidan qat'i nazar, jinoyat.


Keyingi dars: SSRF — serverni o'zi bilmagan holda ichki tarmoqqa so'rov yuborishga majburlash, va nega "faqat men aytgan manzilga boradi" degan taxmin xato.

10 daqiqa 45 marta o‘qildi