JWT (JSON Web Token), modern API auth''un fiili standardıdır. Ama yanlış kullanıldığında tek başına en büyük güvenlik açığına dönüşür. Bu yazı JWT''nin nasıl çalıştığını kısaca özetleyip 5 yaygın saldırı vektörünü ve kalıcı korunma yollarını anlatır.

JWT Yapısı: Hızlı Özet

İlgili rehberler: SSL sertifikası nasıl alınır · OWASP Top 10 2026 · SQL injection önleme · Parola hash (BCrypt, Argon2) · DDoS koruma

Üç bölümden oluşur — Header.Payload.Signature — base64url ile encode edilir ve nokta ile birleştirilir. Header algoritma bilgisi taşır (HS256, RS256), Payload claim''ler, Signature ise header+payload''ın gizli anahtarla imzalanmış halidir.

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwibmFtZSI6ImFkbWluIn0.K7JmD...

Saldırı 1: alg:none

JWT spec''i none algoritmasına izin verir — imzasız token. Bazı eski kütüphaneler bu header''ı görünce imzayı kontrol etmeden kabul eder. Saldırgan payload''u değiştirip signature''u siler, erişim kazanır.

# Saldırı
echo -n '{"alg":"none","typ":"JWT"}' | base64 | tr '/+' '_-' | tr -d '='
# eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0

# Payload değiştir
echo -n '{"sub":"1","role":"admin"}' | base64 | tr '/+' '_-' | tr -d '='

# Token: eyJhbGciOiJub25lIn0.eyJzdWIiOiIxIiwicm9sZSI6ImFkbWluIn0.
# Signature kısmı boş, alg:none olduğu için bazı lib''ler kabul eder
Uyarı
Koruma: verify fonksiyonuna beklediğiniz algoritmayı açıkça geçirin: jwt.verify(token, secret, {algorithms: [''HS256'']})

Saldırı 2: Weak Secret

HS256 symmetric — aynı secret hem imzalar hem doğrular. Secret zayıfsa (sözlük kelimesi, kısa string) saldırgan hashcat ile kırıp istediği token''ı üretir.

# Saldırgan tarafı
hashcat -a 0 -m 16500 token.jwt wordlist.txt
# 'secret', 'secret123', 'password' gibi zayıf secret''ler saniyeler içinde çıkar
// Güçlü secret üretimi
require('crypto').randomBytes(64).toString('hex')
// 128 char hex = 512 bit entropy — brute force imkansız

Saldırı 3: Algorithm Confusion (RS256 → HS256)

RS256 asimetrik — private key imzalar, public key doğrular. Saldırgan public key''i nerelerde duyurulduğuna bakar (jwks endpoint, .pem dosyası), header''ı HS256''ya çevirir ve public key''i HMAC secret olarak kullanıp imzalar. Eğer verify fonksiyonu alg''ı token''dan okuyup buna göre yöntem seçiyorsa kabul eder.

// AÇIK
jwt.verify(token, publicKey);  // alg token''dan okunur!

// KAPALI
jwt.verify(token, publicKey, { algorithms: ['RS256'] });

Saldırı 4: JKU / X5U Injection

JWT header''ında jku (JWK Set URL) claim''i imzalama anahtarının nereden çekileceğini belirtir. Validator bu URL''yi doğrulamadan fetch ederse — saldırgan kendi sunucusuna jku koyup istediği anahtarı kabul ettirir.

// Açık validator
const header = JSON.parse(atob(token.split('.')[0]));
const jwks = await fetch(header.jku).then(r => r.json());  // JKU saldırgan kontrollü!

// Güvenli
const ALLOWED_JKU = 'https://auth.example.com/.well-known/jwks.json';
if (header.jku !== ALLOWED_JKU) throw new Error('Invalid JKU');

Saldırı 5: Kid (Key ID) SQL Injection / Path Traversal

Header''daki kid claim''i anahtar seçmek için kullanılır. Validator bunu DB''de sorgu veya dosya lookup''a verirse — SQLi veya path traversal mümkün.

// TEHLİKE
const key = await db.query(`SELECT pubkey FROM keys WHERE id='${header.kid}'`);
// Saldırgan: kid = "' UNION SELECT 'my_public_key'--"

// GÜVENLI
if (!/^[a-f0-9]{32}$/.test(header.kid)) throw new Error('Invalid kid');
const key = await db.query('SELECT pubkey FROM keys WHERE id=$1', [header.kid]);

Best Practices

  • Algorithm whitelist — verify''a algorithms parametresi geçin
  • Güçlü secret — 256+ bit random, env var''da tut
  • Kısa expiry — access token 15 dk, refresh token 7 gün
  • Revocation — JWT stateless; logout için token blacklist veya kısa TTL
  • HTTPS zorunlu — token MITM ile çalınmasın
  • HttpOnly cookie veya Authorization: Bearer — LocalStorage''a koyma (XSS ile çalınır)
  • Kullanıcı hassas veri koyma — JWT base64, şifrelenmemiş; payload herkes okur
  • iss, aud, sub claim''lerini kontrol et — başka tenant''ın token''ı gelmesin

Refresh Token Rotation

Sıklıkla kullanılan güvenli pattern: kısa ömürlü access token + uzun ömürlü refresh token. Refresh her kullanıldığında rotate edilir (yeni refresh verilir, eski invalide edilir). Eski refresh token tekrar kullanılırsa — hesap compromise edildi demektir, tüm oturumları kapat.

Alternatif: Opaque Token + Redis

JWT''nin stateless yapısı revocation''u zorlaştırır. Birçok durumda daha iyi çözüm: random 256-bit token üret, Redis''te token:abc123 → {user_id, exp, scopes} şeklinde sakla. Avantaj: istediğin an iptal edebilirsin, payload client''a sızmaz.

Web Güvenliği ve Uygulama Savunması

Modern web güvenliği katmanlı savunma (defense-in-depth) ile yapılır: TLS 1.3 ve HSTS ile şifreli iletişim, WAF (Web Application Firewall) ile OWASP Top 10 saldırılarına karşı koruma, BCrypt veya Argon2id ile parola hash'leme, JWT token'larında imza doğrulama (HMAC veya RSA), CSRF token + SameSite cookie ile cross-site istek koruması ve Content Security Policy ile XSS azaltma. SQL injection önleme için prepared statement, brute force için fail2ban veya rate limiting, DDoS koruması için Cloudflare/Anti-DDoS sağlayıcı zorunludur. Güvenlik açığı taraması (Burp Suite, OWASP ZAP) ve düzenli güvenlik denetimi; üretim ortamında veri sızıntısı ve hesap ele geçirme risklerini büyük ölçüde azaltır.

Auth mimarinizi denetleyelim

JWT, OAuth2 ve OIDC güvenlik denetimi için iletişime geçin

WhatsApp