🍪
Session Fixation
Sessiyani majburlash
1
Maqsad
hujumchining sessiyasini qo'pollashLogin qilgandan keyin server sessiya ID'sini almashtirmasa — hujumchi hujumga oldin olgan sessiyani login'dan keyin ham ishlatib qoladi.
2
Tushuntirish
// XAVFLI app.post('/login', (req, res) => {{ if (check(req.body.email, req.body.password)) {{ req.session.userId = findId(req.body.email); // ID O'GARMADI res.redirect('/'); }} }}); // hujum: oldindan sessiya yaratib, qurbonga yuboradi // TO'G'RI app.post('/login', (req, res) => {{ if (!check(...)) return fail(); req.session.regenerate(err => {{ // ← kalit YANGILANADI req.session.userId = findId(req.body.email); res.redirect('/'); }}); }});
Nima uchun muhim
Sessiya ID — bu kalit. Login qilgach kalitni almashtirmaslik — xuddi uyning kalitini almashtirmay qoldirishdek. Hujumchi kalitni oldindan olgan bo'lsa, u hamma uchun ochib qoladi.
3
Qanday aniqlanadi
# 1) session regenerate chaqiruvlari grep -rnE "regenerate|session_regenerate|newSession|invalidate" src/ # 2) session kaliti qayerda saqlanadi grep -rnE "session\(.*secret|cookie.*name|connect\.sid|SESSION_NAME" src/ # 3) kalit uzunligi curl -s -D- -o /dev/null -X POST https://site.uz/api/auth/login \ -H "Content-Type: application/json" -d '{"email":"sinov@site.uz","password":"..."}' \ | grep -i "set-cookie"
4
Buyruqlar
# 1) login DAN OLDIN cookie olish curl -s -c /tmp/jar.txt -o /dev/null https://site.uz/login grep PHPSESSID /tmp/jar.txt BEFORE=$(grep PHPSESSID /tmp/jar.txt | awk '{print $7}') # 2) login qilish (o'siz foydalanuvchi) curl -s -b /tmp/jar.txt -c /tmp/jar.txt -X POST https://site.uz/api/auth/login \ -H "Content-Type: application/json" \ -d '{"email":"sinov@site.uz","password":"..."}' -o /dev/null AFTER=$(grep PHPSESSID /tmp/jar.txt | awk '{{print $7}}') # 3) SOLISHTIRISH [ "$BEFORE" = "$AFTER" ] && echo " ✗ SESSION FIXATION — ID almashilmadi!" \ || echo " ✓ ID almashildi (to'g'ri)" # 4) eski ID bilan kirishni sinab ko'rish curl -s -o /dev/null -w "eski sessiya → HTTP %{http_code}\n" \ https://site.uz/api/me -H "Cookie: PHPSESSID=$BEFORE" # 5) Node.js express-session curl -s -c /tmp/j -X POST https://site.uz/api/auth/login \ -H "Content-Type: application/json" -d '{"email":"a@b.uz","password":"x"}' -D- \ | grep -i "set-cookie" # connect.sid qiymatini login OLDIN va KEYIN solishtiring # 6) header asosidagi sessiya (Bearer emas) curl -s -D- -o /dev/null https://site.uz/ -H "X-Session-Id: test123" # 7) cookie atributlari curl -s -D- -o /dev/null -X POST https://site.uz/api/auth/login \ -H "Content-Type: application/json" -d '{"email":"a@b.uz","password":"x"}' \ | grep -i set-cookie | grep -oE "(HttpOnly|Secure|SameSite=[A-Za-z]+)" | sort -u
5
Natija
✓ MUvaffaqiyat — hujum ISHLADI
| Server javobi | Nima degani |
|---|---|
Login oldidan keyin `Set-Cookie` <b>yo'q</b> | **Fixation — ID o'zgarmadi** |
`PHPSESSID` bir xil qoldi | **Zaiflik tasdiqlandi** |
Eski sessiya bilan `/api/me` → 200 | **Sessiya o'g'rilgan bo'lishi mumkin** |
Kalit 16 belgi (< 128 bit) | **Brute force oson** |
Cookie da `HttpOnly` yo'q | **JS orqali o'g'riladi** |
✗ Rad etish — hujum ISHLAMADI
| Server javobi | Nima degani |
|---|---|
Login'dan keyin `Set-Cookie` yangi sessiya berdi | **To'g'ri** |
Eski sessiya → 401 | **To'g'ri** — bekor qilingan |
`HttpOnly; Secure; SameSite=Strict` bor | **To'g'ri konfiguratsiya** |
Kalit 256 bit (43 belgi base64url) | **Xavfsiz** |
6
Zararni yopish
1. Login'da sessiyani yangilash
// Express app.post('/login', async (req, res) => {{ if (!await check(req.body)) return fail(); req.session.regenerate(err => {{ // ← MUXIM req.session.userId = user.id; req.session.save(() => res.json({{ success:true }})); }}); }}); // PHP session_start(); if (login_ok()) {{ session_regenerate_id(true); // true = eski fayl o'chirilsin $_SESSION['user_id'] = $id; }} // Django / Flask request.session.cycle_key() # Django session.clear(); session['uid'] = uid # Flask
2. Logout'da to'liq tozalash
req.session.destroy(() => res.clearCookie('connect.sid'));
3. Kuchli kalit va atributlar
app.use(session({{
name: '__Host-sid', // __Host- = Secure + Path=/ + __Host prefix
secret: process.env.SESSION_SECRET, // 32+ bayt
cookie: {{ httpOnly:true, secure:true, sameSite:'strict', maxAge: 1800000 }},
resave: false, saveUninitialized: false
}}));
// PHP
ini_set('session.use_strict_mode', 1); // ← server ID'ni majburlaydi
ini_set('session.use_only_cookies', 1);
ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_samesite', 'Strict');
4. 2FA'da ham
// 2FA o'tgan keyin ham regenerate — aks holda vaqtinchalik // token oldindan kelgan sessiyaga bog'liq qoladi
7
Tekshirish ro'yxati
- Login'da `session_regenerate_id` / `regenerate()` bor
- Logout'da `destroy()` va cookie tozalanadi
- Sessiya kaliti 256 bit (43+ belgi)
- `HttpOnly`, `Secure`, `SameSite=Strict`
- `use_strict_mode=1` (PHP)
- 2FA'dan keyin ham sessiya yangilanadi
- Login oldidan keyin cookie solishtirildi