Asosiy kontentga o‘tish

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

Autentifikatsiya: login sahifasi eng ko'p hujum qilinadigan eshik

Login — saytning old eshigi, va hujumchi uni uch tomondan sinaydi: kim mavjudligini bilib olish, parolni terib topish, va 2FA ni chetlab o'tish. Beshta labda buni ishga tushiramiz, keyin Django'da qanday to'g'ri yopishni ko'ramiz.

security backend api

Mundarija

Login sahifasi — saytning old eshigi, va aynan shuning uchun eng ko'p hujum qilinadigan joy. Bu darsda hujum bitta zaiflikka emas, eshikning o'ziga qaratiladi: kim mavjudligini bilib olish, parolni terib topish, qo'shimcha himoyani (2FA, "esda saqlash" cookie) chetlab o'tish.

Ko'p dasturchi login mantig'ini "parol to'g'ri bo'lsa kiritamiz" deb qisqartiradi. Amalda esa login ko'p qatlamli: kim mavjud, necha marta urinildi, ikkinchi omil bormi, cookie qanchalik ishonchli. Har qatlamda alohida xato bo'lishi mumkin.

Bu darsdan keyin siz login sahifasidagi uch xil zaiflikni topa olasiz va Django'da autentifikatsiyani to'g'ri, oqmaydigan qilib qura olasiz.

Bu dars kimga

1-dars (Burp) tugagan bo'lsin. Burp Intruder bilan tanish bo'lsangiz osonroq — bu darsda ko'p ishlatiladi.

Buzilgan taxmin#

Bu darsning taxmini deyarli har bir login sahifasida bor:

"Parol to'g'ri bo'lsa kiritaman, aks holda 'xato' deyman. Bo'ldi."

Bu mantiq uch teshik qoldiradi:

  • Javob farqi. "Foydalanuvchi topilmadi" va "parol xato" — ikki xil javob. Shu farq hujumchiga kim mavjudligini aytadi.

  • Cheklovsiz urinish. Parolni cheksiz terib ko'rish mumkin bo'lsa, uni topish faqat vaqt masalasi.

  • Zaif ikkinchi omil. 2FA qo'shilgan, lekin mantig'i bo'sh joy qoldirgan — uni chetlab o'tish mumkin.

Login — bitta tekshiruv emas, zanjir. Zanjir eng zaif halqasi qadar mustahkam, va hujumchi aynan o'shani qidiradi.

Atamalar#

Atama Ma'nosi
authentication kimligini isbotlash (login)
username enumeration qaysi username mavjudligini javob farqidan bilib olish
brute-force parolni ro'yxatdan ketma-ket terib ko'rish
credential stuffing boshqa saytdan o'g'irlangan parollarni sinash
2FA / MFA ikki/ko'p omilli tasdiqlash (parol + kod)
rate limiting urinishlar sonini cheklash
account lockout ko'p xato urinishdan keyin hisobni vaqtincha yopish
X-Forwarded-For so'rov kelgan IP'ni ko'rsatuvchi sarlavha (soxtalashtiriladi)
stay-logged-in cookie "esda saqlash" cookie'si — mazmuni bashorat qilinmasin
timing attack javob vaqti farqidan axborot chiqarish

Nazariya: login bitta emas, uch qatlam#

Zaif login odatda hamma narsani bitta javobga jamlaydi:

Python
# Zaif: javob farqi username'ni oshkor qiladi, urinish cheklanmaydi
from django.contrib.auth import login as auth_login


def login_view(request):
    user = User.objects.filter(username=request.POST["username"]).first()
    if user is None:
        return render(request, "login.html", {"error": "Bunday foydalanuvchi yo'q"})
    if not user.check_password(request.POST["password"]):
        return render(request, "login.html", {"error": "Parol noto'g'ri"})
    auth_login(request, user)  # django.contrib.auth.login — sessiyani boshlaydi

Ikki xil xato xabari — Bunday foydalanuvchi yo'q va Parol noto'g'ri — hujumchiga kim mavjudligini aytadi. Cheklov yo'q — parolni cheksiz terib ko'rish mumkin. Ikkalasi birga: hujumchi avval haqiqiy username'larni yig'adi, keyin faqat ularga parol teradi.

Kuzating

login javobini diqqat bilan solishtiring — xato matni, javob kodi, sahifa uzunligi, hatto javob vaqti. Ikki urinish orasida eng kichik farq ham — username mavjudligining signali.

Amaliyot#

1-labJavob farqidan username#

Lab: Username enumeration via different responses · APPRENTICE

Vazifa: haqiqiy username'ni topib, uning parolini terib kirish.

Nimani ko'rasiz: login forma va berilgan ikki ro'yxat — username'lar va parollar.

Savol: noto'g'ri username va noto'g'ri parol bir xil javob beradimi? Agar farq bo'lsa, o'sha farq nimani aytadi?

Eng oddiy tekshiruv: Burp Intruder bilan username'larni sinang, boshqa javob (xato matni yoki uzunligi) qaytarganini toping.

Bu eng aniq holat: "Invalid username" va "Incorrect password" — ochiq farq. Hujumchi avval username'ni topadi (bitta javob boshqalaridan farq qiladi), keyin faqat o'shanga parol teradi. Ikki qadamli hujum, lekin birinchi qadamni sizga login sahifasi o'zi sovg'a qildi.

2-labNozik javob farqi#

Lab: Username enumeration via subtly different responses · PRACTITIONER

Vazifa: yana username'ni topib kirish, lekin bu safar farq nozik.

Nimani ko'rasiz: xato xabari deyarli bir xil — bitta nuqta, bo'sh joy yoki bosh harf farq qilishi mumkin.

Savol: xabar bir xil ko'ringani bilan, aynan bir xilmi? Bitta belgi farqi ham — signal.

Eng oddiy tekshiruv: Intruder javoblarini "grep" yoki uzunlik bo'yicha solishtiring, eng kichik farqni qidiring.

Dasturchi xatolarni "bir xil qildim" deb o'ylaydi, lekin bittasida nuqta qolib ketadi, boshqasida katta harf. Kompyuter uchun bir belgi ham farq. Saboq: himoya deyarli bir xil emas, aynan bir xil bo'lishi kerak — "deyarli" hujumchiga yetarli.

3-labVaqt farqi va IP chetlash#

Lab: Username enumeration via response timing · PRACTITIONER

Vazifa: vaqt farqidan username topish, IP bloklovini X-Forwarded-For bilan chetlab o'tib, parolni terish.

Nimani ko'rasiz: javoblar bir xil, lekin haqiqiy username uchun server parolni tekshiradi — bu vaqt oladi.

Savol: javob matni bir xil bo'lsa ham, javob vaqti bir xilmi? IP bloklovini qanday chetlab o'tasiz?

Eng oddiy tekshiruv: uzun parol yuboring va javob vaqtini kuzating; X-Forwarded-For ni har so'rovda o'zgartiring.

Bu ikki saboq beradi. Birinchi: axborot javob matnida bo'lmasa ham, javob vaqtida bo'lishi mumkin — haqiqiy username uchun server parol hashini tekshiradi, bu sekinroq. Ikkinchi: IP bo'yicha bloklov X-Forwarded-For ga ishonsa, hujumchi uni har so'rovda o'zgartirib cheklovni umuman yo'q qiladi. Soxtalashtiriladigan sarlavhaga ishonch — himoyani ochiq qoldiradi.

4-lab2FA ni chetlab o'tish#

Lab: 2FA simple bypass · APPRENTICE

Vazifa: carlos hisobiga 2FA'ni chetlab o'tib kirish (carlos:montoya).

Nimani ko'rasiz: login → 2FA kodi → hisob. Ikki bosqichli.

Savol: parol bosqichidan keyin siz allaqachon qisman kirdingiz. 2FA sahifasini o'tkazib yuborib, to'g'ridan hisob sahifasiga borsangiz — server to'xtatadimi?

Eng oddiy tekshiruv: login qiling, 2FA sahifasida to'xtamasdan, hisob sahifasi URL'iga to'g'ridan o'ting.

2FA qo'shilgan, lekin mantig'i bo'sh: parol to'g'ri bo'lgach, server sizni "qisman kirgan" deb belgilaydi va hisob sahifasini 2FA'siz ham ochadi. Ikkinchi omil bor, lekin u majburiy emas — shunchaki qo'shimcha sahifa. Himoya faqat qo'yilgani yetmaydi; u chetlab o'tib bo'lmaydigan qilib qo'yilishi kerak.

5-lab"Esda saqlash" cookie'sini terish#

Lab: Brute-forcing a stay-logged-in cookie · PRACTITIONER

Vazifa: carlos ning "esda saqlash" cookie'sini yasab, hisobiga kirish.

Nimani ko'rasiz: cookie mazmuni bashorat qilinadigan — username base64, password esa MD5 hash.

Savol: cookie mazmuni formulaga bo'ysunsa (base64(user):md5(parol)), uni o'zingiz yasay olasizmi? Parollar ro'yxatidan har birini shu formula bilan sinasangiz?

Eng oddiy tekshiruv: cookie tuzilishini oching, parollar ro'yxatini md5 bilan qayta ishlab, har birini sinang.

"Esda saqlash" cookie'si — yashirin parol. U bashorat qilinadigan formuladan yasalsa (username + parol hash), hujumchi cookie'ni serverga so'rov yubormasdan yasay oladi va rate limiting'ni umuman chetlab o'tadi. Cookie ichida sir bo'lishi kerak edi; formula esa sir emas.

Nima ishlamaydi va nega#

"Xato xabarini 'noto'g'ri login yoki parol' qildim." To'g'ri qadam, lekin yetarli emas — 2 va 3-lab: nozik matn farqi, javob vaqti ham username'ni oshkor qiladi. Javob hamma jihatdan bir xil bo'lishi kerak.

"IP bo'yicha bloklov qo'ydim." 3-lab: X-Forwarded-For ga ishonsangiz, u soxtalashtiriladi. Bloklov chinakam ulanish manzili bo'yicha bo'lishi kerak.

"2FA qo'shdim." 4-lab: 2FA qo'yilgani yetmaydi — u majburiy, chetlab o'tib bo'lmaydigan qilinishi kerak. Bosqichni o'tkazib yuborib bo'lsa, u himoya emas.

Endi yopamiz#

Django autentifikatsiya tizimi bu zaifliklarning ko'pini qutidan chiqib yopadi — kerak bo'lgani uni to'g'ri ishlatish.

1. Bir xil javob — username oqmasin. Hech qachon "foydalanuvchi yo'q" va "parol xato" ni ajratmang:

Python
# To'g'ri: authenticate ikkalasini birlashtiradi, bitta javob qaytadi
from django.contrib.auth import authenticate, login as auth_login


def login_view(request):
    user = authenticate(
        request,
        username=request.POST["username"],
        password=request.POST["password"],
    )
    if user is None:
        # Bitta xabar: username to'g'rimi yo'qmi — bilinmaydi
        return render(request, "login.html", {"error": "Login yoki parol noto'g'ri"})
    auth_login(request, user)

authenticate() username topilmasa ham parol hashini baribir tekshiradi — ya'ni javob vaqti ham teng bo'ladi (3-labdagi timing hujumi yopiladi).

2. Urinishni cheklang (rate limiting). Login sahifasiga uni albatta qo'ying: django-axes yoki o'z rate limiter'ingiz. Chinakam ulanish IP'si bo'yicha, X-Forwarded-For bo'yicha emas (ishonchli proksi ortidan to'g'ri o'qing).

3. Kuchli parol siyosati + parol hash. Django parolni PBKDF2/argon2 bilan hash qiladi — hech qachon ochiq yoki md5 bilan saqlamang (5-lab aynan md5 ni terdi).

4. 2FA majburiy va chetlab o'tib bo'lmaydigan bo'lsin. Ikkinchi omil tasdiqlanmaguncha sessiya to'liq kirmagan hisoblansin.

Muhim

"esda saqlash" cookie'sini o'zingiz formuladan yasamang. Django sessiya freymvorki cookie'ga faqat imzolangan, mazmunsiz ID qo'yadi — uni tashqaridan yasab bo'lmaydi. O'z cookie sxemangizni ixtiro qilmang.

Eslatma: bu saytda hozircha login yo'q — u faqat anonim sessiya cookie'sini ishlatadi (mehmon belgisi, layk holati). Ya'ni bu darsdagi zaifliklar hozir bu saytga tegishli emas. Lekin kelajakda auth qo'shilsa, yuqoridagi to'rt qatlam — bir xil javob, rate limiting, kuchli hash, majburiy 2FA — birinchi kundan qo'yilishi kerak.

Nazorat savollari#

  1. username enumeration nima? Login sahifasi uni qanday oshkor qiladi?
  2. "Foydalanuvchi yo'q" va "parol xato" ni ajratish nega xavfli?
  3. Javob matni bir xil bo'lsa ham, username qanday oqib chiqishi mumkin (3-lab)?
  4. X-Forwarded-For ga tayangan IP bloklov nega yiqiladi?
  5. 4-labda 2FA qanday chetlab o'tildi? "Qo'yilgani yetmaydi" nimani anglatadi?
  6. "Esda saqlash" cookie'si nega bashorat qilinadigan bo'lmasligi kerak (5-lab)?
  7. Django'ning authenticate() funksiyasi timing hujumidan qanday himoya qiladi?
  8. Nega parolni md5 bilan saqlash xavfli? Django nima ishlatadi?
  9. Login sahifasiga rate limiting nega alohida muhim?
  10. Nega o'z sessiya cookie sxemangizni ixtiro qilmaslik kerak?

Report uchun talablar#

  1. Skrinshot: kamida bitta labda hisobga kirgan holat.
  2. Enumeratsiya: 1, 2 yoki 3-labda haqiqiy username'ni qaysi signal bilan topdingiz (matn / uzunlik / vaqt)?
  3. Chetlash: 4 yoki 5-labda himoyani qanday chetlab o'tdingiz? O'z so'zingiz bilan yozing.
  4. Tuzatuvchi kod: yuqoridagi zaif login funksiyasini oling (yoki o'z loyihangizdan) va uni authenticate() + bir xil javob + rate limiting bilan yoping. Oldingi va keyingi holatni keltiring.

Faqat ruxsat berilgan joyda

Parol terish va hisob egallash — jiddiy jinoyat. Bu texnikalarni faqat PortSwigger laboratoriyasida yoki o'zingizga tegishli tizimda sinang. Birovning hisobiga kirishga urinish — natijasidan qat'i nazar, jinoyat.


Keyingi dars: Path traversal — fayl nomi shunchaki fayl nomi emas, va server nega o'zi kutmagan fayllarni ochib berishi mumkin.

10 daqiqa 89 marta o‘qildi