RƏSƏDXANA

Həftə 5 · 10/23

Sessiya, limitlər və sızmalar

6 dəqiqəlik oxu

Otelə çatırsan, resepsiyon sənə bir kart verir. Bundan sonra hər qapıda adını demirsən, kartı oxudursan. Kart üçüncü mərtəbədə işləyir, birincidə işləmir. Çıxanda təhvil verirsən və kart ölür. PIN-i üç dəfə səhv yazsan, kilidlənir.

Sessiya elə həmin kartdır. Giriş edəndə server sənə token verir, sonra hər sorğuda onu göstərirsən. Kartın hansı qapılarda keçdiyini cookie ayarları həll edir: SameSite, Secure, HttpOnly. Neçə səhv cəhdə icazə verildiyini isə limit.

Set-Cookie: sid=abc; HttpOnly; Secure; SameSite=None
//                        |         |        |
//   JavaScript can't read it       |        sent to another domain too
//                        only over HTTPS
Bir sətir, üç qərar. SameSite=Lax yazsaydın, saytın və API-n ayrı domendə olduğu üçün brauzer bu kartı heç göndərməzdi. Lokalda fərqi bilməzdin, canlıda isə hamı anonim olardı.

Çox deyilən söz: Giriş işləyir, deməli auth bitdi.

Auth bir ekran deyil, bir ömürdür. Token necə daşınır, nə vaxt ölür, neçə dəfə səhv yazıla bilər, hansı məlumat yan-yörədən sızır, nə qədər log qalır. Bunların heç biri giriş ekranında görünmür. Hamısı giriş işlədikdən sonra başlayır.

Uğursuzluqları say, sayğacı yaz

Parol axtaran adam ardıcıl səhv edir. Deməli sayılacaq şey də odur. Bir də sayğacın harada saxlandığına bax: serverless-də hər instansiyanın yaddaşı ayrıdır və tez sıfırlanır, ona görə sayğac paylaşılan yerdə (DB və ya KV) yazılmalıdır.

Sən bunu istə

if (await limits.blocked(key)) return tooMany();
const ok = await verify(password, hash);
if (!ok) await limits.recordFailure(key);   // count failures
else await limits.reset(key);

Naməlum istifadəçiyə və səhv parola eyni cavab

İki fərqli mesaj yazsan, hücumçu əlindəki siyahı ilə gəlib hansı ünvanların qeydiyyatda olduğunu asanlıqla öyrənir. Ona görə hər iki halda eyni cümləni göstər və cavab vaxtını da bir-birinə yaxın saxla.

AI belə yazır

if (!user) return error("No account with this email");
if (!ok)   return error("Wrong password");

Sən bunu istə

if (!user || !ok) return error("Email or password is incorrect");

Cookie-ni kimin alacağını atributlar həll edir

HttpOnly cookie-ni JavaScript-dən gizlədir, yəni brauzerdə işləyən bir skript onu oxuya bilmir. Secure onu yalnız HTTPS-ə buraxır. SameSite isə ən çox yanılınan hissədir: saytın bir domendə, API-n başqa domendədirsə, Lax həmin cookie-ni göndərmir və sən bunu ancaq canlıda görürsən.

Sən bunu istə

Set-Cookie: sid=...; HttpOnly; Secure; SameSite=None; Path=/; Max-Age=2592000

Diff oxuyanda soruş: Limitin koduna bax. Uğurlu girişləri sayır, yoxsa uğursuzları? Sayğac həqiqətən yazılır, yoxsa ancaq oxunur? Bir də xəta mesajını oxu: «belə hesab yoxdur» deyirsə, hücumçuya hansı e-poçtların qeydiyyatda olduğunu öyrədirsən.

Terminlər

SameSite
Cookie-nin başqa saytdan gələn sorğularla göndərilib-göndərilmədiyini təyin edir. Sayt və API ayrı domendədirsə, Lax cookie-ni göndərmir.
HttpOnly / Secure
HttpOnly: JavaScript cookie-ni oxuya bilməz. Secure: yalnız HTTPS ilə gedir.
rate limiting
Müəyyən vaxtda cəhd sayını məhdudlaşdırmaq. Hansı cəhdləri saydığın vacibdir.
user enumeration
Xəta mesajlarından hansı hesabların mövcud olduğunu öyrənmək.
PII
Şəxsi məlumat: e-poçt, IP, ad. Harada saxlanıldığını və görsəndiyini bilməlisən.
key derivation (PBKDF2 / Argon2)
Parolu yavaş hash-ə çevirmək ki, oğurlanmış baza asanlıqla sındırılmasın.
data retention
Hər növ məlumatın nə qədər saxlanıldığı və nə vaxt silindiyi.

İndi sən yoxla

1Bu giriş limiti nəyi səhv edir?

if (await limiter.tooMany(ip)) return tooManyRequests();
const ok = await verify(password, user.hash);
if (ok) await limiter.record(ip);

2Sayt example.pages.dev-də, API api.example.workers.dev-də. Cookie SameSite=Lax. Daxil olmuş sorğular anonim gəlir. Niyə?

Hazır prompt

İngiliscədir, çünki terminlər ingiliscədir. Tərcümə etsən də terminləri saxla.

prompt
Review the auth flow end to end: sign-up, login, logout,
password reset, email verification.

For each step:
- What is rate limited, and what exactly is counted (success or failure)?
  Is the counter written, not just read?
- Could an attacker learn whether an account exists?
- Where is PII (email, IP) stored, shown or logged, and for how long?
- How is the session sent (cookie attributes, header), and does that
  work across the domains we actually deploy to?

List concrete failure scenarios, not general advice.

Öz kodunda

  1. 1AI-a skript yazdır: 10 uğursuz giriş et və 11-cinin bloklandığını yoxla.
  2. 2Eyni skriptdə üç cihazdan uğurlu girişin bloklanmadığını da yoxla.
  3. 3İnterfeysdə e-poçtun göründüyü hər yeri tap. Hər biri lazımdırmı?

Bunu görəndə bitib: Limit testi keçir, şəxsi məlumatın harada yaşadığını və nə qədər saxlanıldığını bilirsən.

Daha dərinə

Oxumaq üçün