Skip to content
Bloga Dönün
Güvenlik

JWT Güvenliği: En İyi Uygulamalar, Saldırılar ve Savunma

JWT güvenliğini sağlayın: alg:none ve algoritma karışıklığı saldırılarını durdurun, algoritmaları sabitleyin, anahtarları döndürün ve claim doğrulayın.

13 dakika okuma

JWT Güvenliği: Saldırılar, Savunmalar ve 2026 Kontrol Listesi

JSON Web Token’ları modern kimlik doğrulamanın büyük bölümünü çalıştırır, ama onları güvende tutan uygulamalar olması gerekenden çok daha sık atlanır. JWT, OAuth 2.0, OpenID Connect ve mikroservisler arasındaki servis-servise çağrılar için fiilî kimlik bilgisi biçimi. Aynı zamanda her yıl düzenli bir CVE akışının kaynağı ve bunların neredeyse tamamı aynı kaçınılabilir hatalara dayanıyor: imzasız token kabul etmek, saldırganın seçtiği algoritmaya güvenmek, zayıf bir imzalama gizli anahtarı kullanmak, claim doğrulamasını atlamak.

Bir JWT’nin güvenli olması için dört koşulun aynı anda sağlanması gerekir: imza bozulmamış, algoritma bir saldırganca değiştirilemez, claim’ler gerçekten denetleniyor ve token kolayca çalınamayacağı bir yerde saklanıyor. Bunlardan birini çiğnerseniz elinizde sertleştirilmiş bir API değil, bir kimlik doğrulama atlaması kalır. Bu rehber önce en çok önem taşıyan üç saldırıyı, ardından savunmaları ele alıyor: algoritma seçip sabitleme, anahtar yönetimi, claim doğrulama ve token saklama. En sonda da doğrudan bir incelemeye yapıştırabileceğiniz bir kontrol listesi bulacaksınız.

Bir JWT İmzası Sizi Aslında Nasıl Korur (ve Neyi Korumaz)

Herhangi bir saldırıyı anlamadan önce şunu netleştirin: bir JWT şifrelenmemiştir, yalnızca kodlanmıştır. İmzalı bir token noktalarla birleştirilmiş üç Base64URL parçasından oluşur: header.payload.signature. Başlık ve yük, JSON’un düz Base64URL halidir. Token’a sahip olan herkes içindeki her claim’i okuyabilir. Herhangi bir token’ı JWT çözücü aracımıza yapıştırdığınızda başlık ve yükü, hiçbir anahtar gerekmeden okunabilir JSON olarak görürsünüz. Yük tasarım gereği herkese açıktır.

Peki güvenlik nereden geliyor? Yalnızca imzadan. İmza, başlık ve yük üzerinden bir gizli anahtar (HMAC) ya da bir özel anahtar (RSA, ECDSA) kullanılarak hesaplanan kriptografik bir değerdir. Saldırgan token’ı serbestçe okuyabilir, ama imzalama anahtarı olmadan doğrulamadan geçecek farklı bir token üretemez. Güven modelinin tamamı bu tek özelliğe dayanır.

Bundan iki sonuç çıkar. Birincisi, yüke asla gizli bilgi koymayın (parolalar, API anahtarları, eksiksiz PII), çünkü token’ı yakalayan herkes bunu okuyabilir. İkincisi, tüm güvenlik duruşunuz tek bir adıma, imzayı doğru biçimde doğrulamaya dayanır. Saldırganların hedef aldığı adım da tam olarak budur. Token’ları parça parça okumayı daha ayrıntılı görmek için JWT nasıl çözülür yazısına bakın.

3 Kritik JWT Saldırısı (ve Her Birini Nasıl Durdurursunuz)

JWT açıklarının çoğu aynı temanın varyasyonudur: sunucu, saldırganın denetlediği bir şeye güvenir. Aşağıda kimlik doğrulamayı doğrudan kıran üç tanesini, her birinin ardındaki mekanizma ve çözümle birlikte bulacaksınız.

1. alg:none Saldırısı — İmzasız Token Atlaması

JWS spesifikasyonu, “imzasız” anlamına gelen none değerinde bir alg içerir. Bir alg:none token’ının imza parçası boştur ve yine de header.payload. gibi sonda bir noktayla biter. Saldırı basit: geçerli bir token alın, başlığın alg değerini none yapın, istediğiniz claim’leri (diyelim ki "role": "admin") yerleştirin ve imzayı atın. İlk dönem JWT kütüphaneleri bunu varsayılan olarak kabul ediyordu, dolayısıyla sahte token doğrulamadan rahatça geçiyordu. Anahtar yok, imzalama yok, tam bir kimliğe bürünme.

Böyle bir token’ın nasıl göründüğünü JWT çözücü aracımızda “alg:none” örneğini yükleyerek görebilirsiniz. Araç, token’ın imzasız olduğunu ve kimlik doğrulama için asla kabul edilmemesi gerektiğini belirten açık bir kırmızı uyarı verir. Kendiniz bir tane oluşturmak, tehdidi anlamak için bir dakikalık bir iştir.

Savunma, her doğrulama çağrısında açık bir algoritma izin listesi kullanmaktır. Neyin kabul edilebilir olduğuna kütüphanenin varsayılanının karar vermesine asla izin vermeyin; eski varsayılanlar fazla hoşgörülüydü ve algoritmayı açıkça belirtmenin maliyeti yalnızca fazladan bir seçenek.

// WRONG — the library may accept alg:none or any algorithm
jwt.verify(token, key);

// RIGHT — pin the exact algorithm you expect
jwt.verify(token, key, { algorithms: ['RS256'] });

none o dizide asla görünmemelidir. Kütüphaneniz algoritmaları sabitleyemiyorsa onu değiştirin.

2. Algoritma Karışıklığı — RS256’nın HS256’ya Düşürülmesi

Pratikte en tehlikeli JWT açığı budur; 2015’ten beri biliniyor ve bugün hâlâ denetimlerde karşımıza çıkıyor. Doğrulamanın nasıl yapılacağına başlıktaki alg alanına bakarak karar veren sunucuları sömürür, ki bu da token’ın saldırganın yeniden yazabildiği tek parçasıdır.

Mekanizma şöyle işliyor. Sunucunuz RS256 token’ları yayımlar: bir RSA özel anahtarı ile imzalar, eşleşen genel anahtar ile doğrular. Bu genel anahtar tanımı gereği geneldir; JWKS uç noktanızda ya da deponuzda bulunabilir. Saldırgan onu alır, token başlığını RS256’dan HS256’ya çevirir ve genel anahtar dizesini HMAC gizli anahtarı olarak kullanarak HMAC-SHA256 ile sahte bir yükü imzalar. Doğrulama tarafına gelince: kodunuz alg’ı başlıktan okuyup buna göre HMAC seçerse, aynı genel anahtarı gizli anahtar olarak kullanarak token üzerinden HMAC-SHA256 hesaplar. İmzalar eşleşir. Sahte token kabul edilir.

Bunun arkasında çarpışan iki gerçek var: doğrulayıcı saldırganın denetlediği alg başlığına güvendi ve RSA genel anahtarı, HMAC anahtarı olarak kullanılmak üzere saldırgana açıktı. Bu gerçeklerin hiçbiri tek başına bir kusur değil. Bir genel anahtarın genel olması gerekir ve bir alg başlığının token’ı tanımlaması gerekir. Açık, doğrulama mantığınız bu başlığın hangi anahtar türü ve algoritmanın kullanılacağını seçmesine izin verdiği an doğar; o zaman saldırganın yazdığı bir değer, sunucunun çalıştırdığı kripto yolunu yönlendirir.

// WRONG — verification method follows the header's alg field
jwt.verify(token, publicKeyOrSecret);

// RIGHT — hard-code the expected algorithm; never let the header choose
jwt.verify(token, publicKey, { algorithms: ['RS256'] });

Asimetrik algoritmayı açıkça sabitleyin (yalnızca RS256 ya da ES256), HMAC doğrulamasını RSA doğrulamasından tamamen ayrı bir kod yolunda tutun ve anahtar türlerini birbirinden ayıran, bakımı sürdürülen bir kütüphane kullanın. JWT çözücü aracımız, tam da bu saldırı çok yaygın olduğu için, HS ailesinden herhangi bir token’ı genel-anahtar-karışıklığı uyarısıyla işaretler. Asimetrik olmasını beklediğiniz bir token HS256 olarak çıktığında, o uyarı sizin işaretinizdir.

3. Zayıf HMAC Gizli Anahtarı — Kaba Kuvvet ve Sözlük Saldırıları

HMAC (HS256/384/512) kullandığınızda, token’ın tüm güvenliği tek bir gizli anahtarın entropisine dayanır. Bu gizli anahtar kısaysa, bir sözlük sözcüğüyse ya da secret veya password123 gibi bir değerse, tek bir geçerli token’ı yakalayan saldırgan onu çevrimdışı kırabilir. hashcat gibi araçlar, token’ın imzasına karşı saniyede milyarlarca adayı tarar. Gizli anahtar bir kez düştüğünde saldırgan istediği herhangi bir token’ı basabilir; sonsuza dek geçerli admin kimlik bilgileri demektir bu.

Bu saldırıyı sinsice tehlikeli kılan, tümüyle çevrimdışı olması. Saldırgan oturum açma uç noktanızı zorlamaz, yani tetiklenecek bir hız sınırı ya da günlüklerinizde fark edeceğiniz bir iz yoktur. Tek bir token yakalar, gizli anahtarı kendi donanımında kırar ve ancak sizin tüm denetimlerinizden geçen token’lar imzalayabildiğinde geri döner. Çözüm pazarlık konusu değil: kriptografik olarak güvenli bir kaynaktan en az 32 rastgele bayt (256 bit) kullanın ve bunu koda ya da depoya değil, bir gizli anahtar yöneticisinde saklayın.

// WRONG — guessable, low entropy, crackable in seconds
const secret = "password123";

// RIGHT — 256 bits from a CSPRNG, then load from KMS at runtime
const secret = require('crypto').randomBytes(32).toString('base64');

Hızlıca güçlü bir değer mi lazım? Şifre üretici aracımız, bir HMAC anahtarı için uygun, yüksek entropili dizeler üretir. Farkı pratikte görmek isterseniz JWT oluşturucu aracımızda güçlü bir gizli anahtarla bir test token’ı imzalayın; her şey tarayıcıda çalıştığı için gizli anahtar makinenizden hiç ayrılmaz. Doğrulama bir güven sınırını aştığında (birden çok servis, üçüncü taraf doğrulayıcılar) HS256 kullanmayı tamamen bırakın ve bir sonraki bölümde ele alınan asimetrik bir algoritmaya geçin.

Doğru Algoritmayı Seçmek ve Sabitlemek

Algoritma seçimi, karışıklık saldırısının kazanıldığı ya da kaybedildiği yer; o yüzden bilinçli seçin. Pratikte gerçekten kullanacağınız üçü şunlar:

AlgoritmaTürİmzalama / doğrulama anahtarıNe zaman kullanılır
HS256Simetrik (HMAC)Tek bir paylaşılan gizli anahtarTek güven sınırı, aynı taraf imzalar ve doğrular
RS256Asimetrik (RSA)Özel anahtar imzalar / genel anahtar doğrularServisler arası, üçüncü taraf doğrulama, JWKS döndürme
ES256Asimetrik (ECDSA)Özel anahtar imzalar / genel anahtar doğrularRS256 ile aynı, daha küçük ve hızlı anahtarlar — yeni sistemler için tercih edilir

Kural kısa. Aynı taraf tek bir güven sınırı içinde imzalayıp doğruluyorsa HS256 sorunsuz ve hızlıdır. İmzalayandan başka biri doğrulamak zorundaysa (başka bir servis, bir iş ortağı, herkese açık bir istemci) asimetrik bir algoritma kullanın ve ES256’yı tercih edin: anahtarları ve imzaları, eşdeğer güçte RSA’dan çok daha küçüktür. Örnek HS256, RS256 ve ES256 token’larını yan yana imzalayıp yapılarını ve imza uzunluklarını karşılaştırmak için JWT oluşturucu aracını kullanabilirsiniz.

Hangisini seçerseniz seçin, savunma aynı kalır: doğrulama çağrısında tek bir açık algoritma kümesini sabitleyin ve başlıktaki alg alanına asla güvenmeyin. İzin listesi, diğer her şeyin üzerine oturduğu temeldir.

Anahtar Yönetimi ve Döndürme

Algoritmalar ancak arkalarındaki anahtarlar kadar güvenlidir ve anahtar yönetimi, çoğu rehberin sustuğu yerdir. HS256 için gizli anahtar en az 32 rastgele bayttır ve bir gizli anahtar yöneticisinde (AWS Secrets Manager, HashiCorp Vault ya da Azure Key Vault) bulunur. Asimetrik algoritmalarda özel anahtar bir HSM ya da KMS’ye aittir ve uygulama koduna asla dokunmaz; genel anahtar ise yayımlanır, genellikle doğrulayıcıların eriştiği bir JWKS uç noktası üzerinden.

Döndürme bir acil durum değil, rutin olmalı. Doğrulayıcıların belirli bir token’ı hangi anahtarın imzaladığını bilmesi için her anahtarı JWT başlığında bir kid (anahtar kimliği) ile etiketleyin. Doğrulama tarafında küçük bir geçerli anahtar kümesi tutun: mevcut anahtar ve yakın zamandaki bir öncekisi. Böylece bir döndürmeden hemen önce imzalanan token’lar ömürleri boyunca hâlâ doğrulanır. Döndürmeyi bir kesinti olmaktan çıkarıp sorunsuz kılan da bu örtüşmedir.

Anahtarlar için kısa bir kontrol listesi:

  • İmzalama anahtarlarını en az 90 günde bir, herhangi bir ele geçirilme şüphesinde ise hemen döndürün.
  • Genel anahtarları JWKS aracılığıyla yayımlayın; kid ile sürümleyin.
  • Özel anahtarları ve HMAC gizli anahtarlarını bir KMS ya da HSM’de tutun; asla git’te, istemci kodunda ya da sabit kodlanmış halde değil.
  • Bir sızıntıda anahtarı döndürün ve bekleyen yenileme token’larını hemen iptal edin.

Atlayamayacağınız Claim Doğrulaması

İmza denetimi, bir token’ın gerçek olduğunu kanıtlar. Token’ın şu anda, sizin için olduğunu kanıtlamaz. İşte claim doğrulaması bunu yapar ve ekleyebileceğiniz en ucuz savunmadır. Her istekte şu beş claim denetlenmeli:

  • exp (sona erme) — sona erme tarihi geçmişte olan token’ları reddedin.
  • nbf (önce değil) — geçerlilik penceresi açılmadan önce kullanılan token’ları reddedin.
  • iat (oluşturulma zamanı) — isteğe bağlı olarak, makul olmayacak kadar eski token’ları reddedin.
  • iss (yayımcı) — token’ın güvendiğiniz yayımcıdan geldiğini doğrulayın.
  • aud (hedef kitle) — token’ın sizin servisiniz için basıldığını doğrulayın. Eksik bir aud denetimi en yaygın sessiz açıktır; bir API için yayımlanan bir token’ın başka birine karşı yeniden oynatılmasına izin verir.

Çoğu kütüphane, beklenen değerleri geçtiğinizde bunları sizin için doğrular:

jwt.verify(token, key, {
  algorithms: ['ES256'],
  issuer: 'https://auth.example.com',
  audience: 'api.example.com',
  clockTolerance: 5, // seconds, for distributed clock skew
});

Sunucular arası küçük kaymanın geçerli token’ları reddetmemesi için küçük bir saat toleransına izin verin; beş saniye tipiktir. Bunu büyütme dürtüsüne direnin: cömert bir tolerans, sona ermiş bir token’ın hâlâ çalıştığı pencereyi genişletir, ki exp tam da bunu kapatmak için var. Bir token’daki exp ve iat değerlerini gözle hızlıca denetlemek için onu JWT çözücü aracına bırakın ve zaman damgalarını Unix zaman damgası dönüştürücü aracımızla dönüştürün.

Token Ömrü ve JWT’leri Nerede Saklamalı

Sunucu tarafı denetimleri hikâyenin yalnızca yarısı. İstemcinin token’ı nerede tuttuğu, onun ne kadar kolay çalınabileceğini belirler; XSS ile oturum ele geçirmenin buluştuğu yer de burası, yani depolama. Sağlam duran kalıp şu: kısa ömürlü bir erişim token’ı (15 ila 60 dakika), iptal edilebilir, ayrı ve daha uzun ömürlü bir yenileme token’ıyla eşleştirilir.

Depolama kararı tek bir ödünleşime iner:

Depolama konumuXSS maruziyetiCSRF riskiÖneri
localStorageYüksek — sayfadaki herhangi bir JavaScript okuyabilirYokOturum token’ları için kaçının
HttpOnly + Secure + SameSite=Strict çerezDüşük — JavaScript’e görünmezCSRF koruması gerekirOturumlar için önerilir

localStorage’daki bir token, sayfada çalışan herhangi bir betik tarafından okunabilir; yani tek bir XSS hatası tüm oturumu sızdırır ve saldırgan onu kendi makinesinden, ömrü boyunca yeniden oynatabilir. Bir HttpOnly çerez ise JavaScript tarafından hiç okunamaz; bu da XSS’in hasarını saldırganın canlı bir sayfa içinde yapabileceğiyle sınırlar. Kötü, ama yanında taşıyabileceği çalınmış bir kimlik bilgisi değil. Çerez yaklaşımının bedeli, artık CSRF korumasına ihtiyaç duymanız, çünkü çerezler her istekte otomatik olarak gelir. SameSite=Strict artı bir CSRF token’ı bunu halleder. Bir sızıntının patlama yarıçapı küçük olsun diye erişim token’ını kısa tutun ve yenileme token’ını bir HttpOnly, Secure, SameSite çereze koyun. Çıkışta ya da ele geçirilme şüphesinde, yenileme token’ını sunucu tarafında iptal edin ve imzalama anahtarını döndürün. XSS, CSRF ve güvenli çerezler hakkında daha geniş bağlam için web güvenliği uygulamaları rehberimize bakın.

JWT Güvenlik Kontrol Listesi

JWT tabanlı herhangi bir kimlik doğrulamayı yayına almadan önce şunları gözden geçirin:

  • Doğrulama, açık bir algoritma izin listesini sabitler ve alg:none’ı reddeder.
  • Asimetrik doğrulama, beklenen algoritmayı sabit kodlar ve alg’ı başlıktan asla okumaz (karışıklığı engeller).
  • HS256 gizli anahtarları en az 32 rastgele bayttır, bir KMS’den yüklenir.
  • Özel anahtarlar bir HSM/KMS’de bulunur; genel anahtarlar JWKS aracılığıyla yayımlanır ve kid ile sürümlenir.
  • İmzalama anahtarları en az 90 günde bir döndürülür.
  • Her istek exp, nbf, iat, iss ve aud değerlerini, 5 saniye ya da daha az bir saat toleransıyla doğrular.
  • Erişim token’ları 15 ila 60 dakika sürer; yenileme token’ları bir HttpOnly çerezde bulunur.
  • Yükte gizli bilgi yok — kodlanmıştır, şifrelenmemiştir.

SSS

JWT varsayılan olarak güvenli mi?

Hayır. JWT güvenliği yapılandırmaya bağlıdır. Algoritmayı sabitlemeli, alg:none’ı reddetmeli, yüksek entropili bir gizli anahtar ya da anahtar kullanmalı ve claim’leri doğrulamalısınız. Varsayılan ya da hoşgörülü kütüphane kurulumları sık sık kimlik doğrulama atlamalarına izin verir.

En tehlikeli JWT açığı nedir?

Algoritma karışıklığı; RS256’nın HS256’ya düşürüldüğü ve genel anahtarın HMAC gizli anahtarı olarak kullanıldığı durum. 2015’ten beri biliniyor, yine de denetimlerde hâlâ ortaya çıkıyor; çünkü doğrulama yöntemini başlığın alg’ından seçen sunucuları sömürür.

HS256 mı yoksa RS256 mı kullanmalıyım?

Aynı taraf tek bir güven sınırı içinde imzalayıp doğruladığında HS256 kullanın. Başka bir servis ya da üçüncü bir taraf doğrulamak zorunda olduğunda ya da JWKS döndürmeye ihtiyaç duyduğunuzda RS256 veya ES256 kullanın. Yeni sistemler için ES256’yı tercih edin: eşit güçte daha küçük, daha hızlı anahtarlar.

Bir JWT’yi nerede saklamalıyım?

Oturum token’ları için bir HttpOnly, Secure, SameSite çerezi tercih edin; çünkü JavaScript onu okuyamaz ve tek bir XSS hatası onu çalamaz. Oturum token’ları için localStorage’dan kaçının — herhangi bir XSS tüm oturumu yeniden oynatma için sızdırır.

JWT imzalama anahtarlarını ne sıklıkla döndürmeliyim?

Rutin olarak en az 90 günde bir, ele geçirilme şüphesinde ise hemen döndürün. Anahtarları kid ile sürümleyin ve doğrulayıcıda hem aktif anahtarı hem de yakın zamandaki bir öncekisini tutun; böylece döndürmeden hemen önce imzalanan token’lar hâlâ doğrulanır.

Bir JWT kurcalanabilir mi?

İmzalama anahtarı olmadan hayır; hiçbir saldırgan doğrulamadan geçecek bir token sahteleyemez. Ancak sunucunuz alg:none’ı kabul ediyorsa, algoritma karışıklığına açıksa ya da zayıf bir gizli anahtar kullanıyorsa imza atlanabilir. Bunlar JWT’nin kendisindeki kusurlar değil, yapılandırma hatalarıdır.

Hangi claim’leri doğrulamalıyım?

exp (sona erme), nbf (önce değil), iat (oluşturulma zamanı), iss (yayımcı) ve aud (hedef kitle) değerlerini doğrulayın. Eksik bir aud denetimi en yaygın sessiz açıktır; bir servis için tasarlanan bir token’ın başka birine karşı yeniden oynatılmasına izin verir.

Sonuç

JWT güvenliği karmaşık değil, ama her katmanın yerinde durması gerekiyor. İmza tek garantiniz, o yüzden onu doğru biçimde doğrulayın. Tek bir açık algoritma sabitleyin ve başlığın alg’ına asla güvenmeyin. Bir KMS’de tutulan güçlü, döndürülmüş anahtarlar kullanın. Her istekte exp, nbf, iat, iss ve aud değerlerini doğrulayın. Token’ları XSS’in ulaşamayacağı bir yerde saklayın.

Bunu pratiğe dökmek için herhangi bir token’ı JWT çözücü aracımıza yapıştırarak algoritmasını ve claim’lerini inceleyin, alg:none ya da HS-karışıklığı risklerini yakalayın; imzalamayı tarayıcınızda denemek için de JWT oluşturucu aracını kullanın. Anahtarlarınız cihazınızdan hiç ayrılmaz.

Etiketler: jwt security authentication oauth api-security