Brute-force himoya
Brute-force (qo‘pol kuch) hujumi — parolni taxmin qilib, ketma-ket sinab ko‘rish. Hujumchi login endpointiga soniyasiga yuzlab so‘rov yuboradi: 123456, password, qwerty, aziza2000 va hokazo. Himoya bo‘lmasa, oddiy parollar bir necha daqiqada topiladi.
Parollarni xeshlash darsida bcrypt o‘g‘irlangan bazadagi xeshlarni ochishni qiyinlashtirishi aytilgan edi. Lekin u login endpointi orqali qilingan hujumdan himoya qilmaydi. Bu yerda hujumchi xeshni emas, to‘g‘ridan-to‘g‘ri serverning o‘zini sinaydi.
Hujum turlari
| Hujum | Qanday ishlaydi | Belgisi |
|---|---|---|
| Klassik brute-force | Bitta akkauntga ko‘p parol | Bitta email, ko‘p muvaffaqiyatsiz urinish |
| Password spraying | Ko‘p akkauntga bitta mashhur parol | Ko‘p email, har biriga 1–2 urinish |
| Credential stuffing | Boshqa saytdan sizib chiqqan email va parol juftlari | Ko‘p email, har biri boshqacha, ko‘pincha turli IP’lardan |
Har bir hujum turi boshqacha himoya talab qiladi. Faqat email bo‘yicha cheklov qo‘yilsa, password spraying uni chetlab o‘tadi. Faqat IP bo‘yicha cheklov esa minglab IP manzilli botnet’larga qarshi ojiz qoladi. Shuning uchun cheklovlar bir nechta kalit bo‘yicha qo‘yiladi.
Himoya strategiyasi
- Akkaunt bo‘yicha cheklov. Bitta email uchun muvaffaqiyatsiz urinishlar sanaladi. Chegaradan oshganda akkaunt vaqtincha bloklanadi va har safar bloklash muddati oshib boradi.
- IP bo‘yicha cheklov. Bitta IP manzildan kelayotgan login urinishlari cheklanadi. Bu password spraying’ga qarshi yordam beradi.
- Bir xil javob. "Email yo‘q" va "parol noto‘g‘ri" holatlari ajratilmaydi. Bu Login / Signup darsida ko‘rilgan.
- Qo‘shimcha choralar: ikki bosqichli autentifikatsiya, sizib chiqqan parollarni tekshirish va monitoring.
Nega butunlay bloklamaslik kerak?
"5 marta xato bo‘lsa, akkaunt administrator ochmaguncha bloklanadi" qoidasi xavfsiz ko‘rinadi. Lekin uning jiddiy kamchiligi bor: hujumchi har qanday foydalanuvchini ataylab bloklab qo‘yishi mumkin. Buning uchun uning emailiga 5 ta noto‘g‘ri parol yuborish kifoya. Bu xizmat ko‘rsatishni rad etish (DoS) hujumining bir turi.
Shuning uchun doimiy bloklash o‘rniga vaqtinchalik va o‘sib boruvchi kechikish ishlatiladi:
1–4-xato: cheklovsiz
5-xato: 1 daqiqa kutish
6-xato: 2 daqiqa
7-xato: 4 daqiqa
...
maksimum: 1 soat
Muvaffaqiyatli login → hisoblagich nolga tushadi
Egasi bir necha daqiqadan keyin baribir kira oladi. Hujumchi uchun esa soatiga bir necha urinish parolni topishga yetmaydi.
Amalga oshirish
LoginGuard
type attempt struct {
failures int
lockedUntil time.Time
lastSeen time.Time
}
type LoginGuard struct {
mu sync.Mutex
attempts map[string]*attempt
threshold int // nechta xatodan keyin bloklash boshlanadi
baseDelay time.Duration // birinchi bloklash muddati
maxDelay time.Duration // eng uzun bloklash
now func() time.Time
}
Har bir kalit uchun muvaffaqiyatsiz urinishlar soni va bloklash tugaydigan vaqt saqlanadi. Kalit sifatida email:[email protected] yoki ip:203.0.113.7 ishlatiladi.
// Check: kalit bloklanganmi? Bloklangan bo‘lsa, qancha kutish kerakligini qaytaradi.
func (g *LoginGuard) Check(key string) (time.Duration, bool) {
g.mu.Lock()
defer g.mu.Unlock()
a, ok := g.attempts[key]
if !ok {
return 0, true
}
if wait := a.lockedUntil.Sub(g.now()); wait > 0 {
return wait, false
}
return 0, true
}
// Fail: muvaffaqiyatsiz urinishni qayd etadi.
func (g *LoginGuard) Fail(key string) {
g.mu.Lock()
defer g.mu.Unlock()
a, ok := g.attempts[key]
if !ok {
a = &attempt{}
g.attempts[key] = a
}
a.failures++
a.lastSeen = g.now()
if a.failures >= g.threshold {
// 5-xato → base, 6-xato → 2×base, 7-xato → 4×base ...
shift := min(a.failures-g.threshold, 16)
delay := min(g.baseDelay<<shift, g.maxDelay)
a.lockedUntil = g.now().Add(delay)
}
}
// Success: muvaffaqiyatli logindan keyin hisoblagich tozalanadi.
func (g *LoginGuard) Success(key string) {
g.mu.Lock()
defer g.mu.Unlock()
delete(g.attempts, key)
}
`g.baseDelay<