OAuth / OIDC zaifliklari

≡ Barcha darslar
Tezkor 🔎 Indeks
🔗

OAuth / OIDC zaifliklari

state, redirect_uri, token
Dars 36 Yuqori o'z saytingizda
1

Maqsad

tashqi login orqali hisobni egallash

OAuth — "Google bilan kirish" tugmasi. Zaif sozlanganida hujumchi o'z akkauntingiz bilan uning hisobiga (yoki aksincha) kiradi.

2

Tushuntirish

asosiy zaifliklar
ZaiflikNima uchun
state yo'q/tekshirilmaydiCSRF — login'ni boshqaga bog'lash
redirect_uri tekshirilmaydi Kodni o'g'irlash (authorization code o'g'irlash)
Token'ni tekshirmaslikBoshqaning token'i bilan hujum
Email'ni ishonchsiz ulashemail_verified ga qaramaslik
Scope kengOrtiqcha huquq (offline_access, email)
Token saqlashDB 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 javobiNima 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 javobiNima 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_secret faqat serverda (`.env`, kodda emas)
  • Access token shifrlangan saqlanadi yoki umuman saqlanmaydi
  • Scope minimal: openid email (kerak bo'lmasa email ham yo'q)
  • Telegram: auth_date 1 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