Saldırı altında mısınız? Olay müdahalesi için bize ulaşın

info@angelforce.eu
Güvenli yazılım geliştirme

JWT güvenliğinde sık yapılan hatalar ve bunlardan kaçınmanın yolları

Sık yapılan JWT hataları ve çözümleri: alg none, RS256/HS256 karışıklığı, zayıf HMAC anahtarları, eksik claim kontrolü, kid enjeksiyonu, iptal ve saklama.

Diğer diller:EnglishDeutschFrançaisEspañolItalianoPolskiNederlandsEesti

İllüstrasyon: JWT güvenliğinde sık yapılan hatalar ve bunlardan kaçınmanın yolları

JSON Web Token’lar (JWT), API kimlik doğrulamasında ve tek oturum açmada (SSO) yaygın olarak kullanılır. Biçim basittir, ancak birçok güvenlik kararını geliştiriciye ve kütüphaneye bırakır. JWT Best Current Practices belgesi olan RFC 8725, bilinen hataları ve bunlardan nasıl kaçınılacağını bir araya getirir; bu yazıda ilk kontrol edeceğimiz hataların üzerinden geçiyoruz.

JWT imzalıdır, gizli değildir

RFC 7519’da tanımlanan imzalı bir JWT, noktalarla ayrılmış üç parçadan oluşur: bir başlık (header), claim’lerden oluşan bir payload ve bir imza. İlk iki parça yalnızca base64url ile kodlanmıştır. Token’a sahip olan herkes bunları okuyabilir. Çözülmüş bir örnek:

{
  "alg": "RS256",
  "typ": "at+jwt",
  "kid": "2026-10-key-1"
}
{
  "iss": "https://auth.example.eu",
  "sub": "user-4821",
  "aud": "api.example.eu",
  "iat": 1792140000,
  "exp": 1792140900,
  "role": "editor"
}

İmza, claim’lerin değiştirilmediğini kanıtlar; onları gizlemez. RFC 7519, bir token gizlilik açısından hassas bilgiler içerdiğinde bu bilgilerin açığa çıkmasını önleyecek önlemler alınması gerektiğini, örneğin şifreli bir JWT (JWE) kullanılabileceğini belirtir. Uygulamada kişisel verileri, kamuya açıklamayacağınız iç tanımlayıcıları ve gizli olan her şeyi payload’un dışında tutun.

Hata 1 - "alg": "none" kabul etmek

RFC 7519, "alg": "none" ve boş imza içeren “güvenliksiz” (unsecured) JWT’lere izin verir. RFC 8725, bu tür token’ları kabul eden ve imza kontrolünü tamamen atlayan kütüphaneleri anlatır. Bu durumda saldırgan istediği claim’leri yazabiliyordu.

RFC 7518, uygulamaların güvenliksiz token’ları varsayılan olarak kabul etmemesi gerektiğini belirtir; OWASP REST Security Cheat Sheet ise bunlara hiç izin verilmemesini söyler. Kütüphanenizin none değerini reddettiğini kontrol edin ve bunu özel olarak hazırlanmış bir token’la test edin.

Hata 2 - algoritmayı token’ın seçmesine izin vermek

Başlıktaki alg değerini token’ı oluşturan kişi seçer; bu kişi bir saldırgan olabilir. RFC 8725 klasik karışıklık (confusion) saldırısını anlatır: sunucu, RSA açık anahtarıyla doğrulanan RS256 bekler. Saldırgan alg değerini HS256 yapar ve token’ı, gizli anahtar olarak bu açık anahtarı kullanarak HMAC ile imzalar. Başlığa uyan bir kütüphane token’ı başarıyla doğrular; açık anahtar ise tanımı gereği herkese açıktır.

Çözüm, algoritmaya sunucuda karar vermektir. OWASP, doğrulamanın algoritmayı seçmek için JWT başlığına dayanmaması gerektiğini söyler. RFC 8725 de her anahtarın tam olarak tek bir algoritmayla kullanılması gerektiğini ekler. Kodda bu, aşağı yukarı şöyle görünür:

verify(token,
       key        = issuer_public_key,
       algorithms = ["RS256"],
       issuer     = "https://auth.example.eu",
       audience   = "api.example.eu")

Hata 3 - zayıf HMAC gizli anahtarları

HS256 kullanıldığında, bir token’ı ele geçiren herkes gizli anahtarı donanımının izin verdiği hızda çevrimdışı tahmin etmeyi deneyebilir. RFC 8725, insanların ezberleyebileceği parolaların doğrudan HMAC anahtarı olarak kullanılmaması gerektiğini belirtir. RFC 7518, en az hash çıktısı uzunluğunda, yani HS256 için 256 bitlik bir anahtar şart koşar.

openssl rand -base64 32

Bu komut 32 rastgele bayt, yani 256 bit üretir. Bunu kod deposunda değil, bir gizli bilgi yöneticisinde (secrets manager) saklayın.

Paylaşılan gizli anahtarların ikinci bir zayıflığı daha vardır. HMAC token’ını doğrulayabilen her servis aynı zamanda token oluşturabilir. OWASP bu nedenle MAC yerine imzaları tercih eder: token’ları birden fazla servis doğruluyorsa, aksi hâlde ele geçirilen tek bir servis hepsi için token üretebilir. RS256 ya da ES256 gibi asimetrik algoritmalar yalnızca açık anahtarı paylaşmanıza olanak tanır.

Hata 4 - claim doğrulamasını atlamak

Geçerli bir imza yalnızca token’ı kimin düzenlediğini kanıtlar. Bu servisin token’ı şu anda kabul edip etmemesi gerektiğine claim’ler karar verir.

  • exp - RFC 7519’a göre token bu zamanda ya da sonrasında kabul edilmemelidir. Saat farkları için genellikle birkaç dakikayı geçmeyen küçük bir tolerans kabul edilebilir.
  • nbf - varsa token’ı bu zamandan önce reddedin.
  • iss - düzenleyenin güvendiğiniz taraf olduğunu ve imzalama anahtarının ona ait olduğunu kontrol edin.
  • aud - RFC 7519’a göre servis kendisini hedef alıcılar (audience) arasında bulamazsa token reddedilmelidir.

OWASP, API erişim token’larında iss, aud ve exp claim’lerinin varsayılan olarak zorunlu tutulmasını ve doğrulanmasını önerir. RFC 8725, hedef alıcının neden önemli olduğunu açıklar: bu claim olmadan bir servis için düzenlenen token, aynı düzenleyene güvenen başka bir serviste yeniden kullanılabilir. RFC 8725 ayrıca typ başlığıyla açık tür belirtilmesini de önerir; böylece bir token türü, başka bir türün beklendiği yerde kullanılamaz. OAuth erişim token’ları için RFC 9068, yukarıdaki örnekte olduğu gibi at+jwt kullanır.

Hata 5 - kid, jku ve x5u’ya güvenmek

Sunucuya anahtarı nerede bulacağını söyleyen başlık parametreleri de saldırganın kontrolündedir. RFC 8725 riskleri şöyle sıralar:

  • Bir veritabanı ya da dizin sorgusunda kullanılan kid (anahtar kimliği), SQL ya da LDAP enjeksiyonuna yol açabilir. Bir dosya yolu oluşturmak için kullanıldığında da aynısı geçerlidir.
  • jku ve x5u, anahtarların çekileceği bir URL’yi gösterir. Herhangi bir URL’yi izlemek sunucu taraflı istek sahteciliğine (SSRF) kapı açar; saldırgan bu adresi kendi anahtarına da yönlendirebilir.

kid değerini anlamı olmayan bir etiket olarak görün ve kontrolünüzdeki sabit bir anahtar listesinde arayın. Anahtarları yalnızca izin verilen URL’ler listesinden çekin; RFC 8725 bu isteklerle çerez gönderilmemesi gerektiğini de ekler.

Hata 6 - uzun ömürlü token’lar ve iptal mekanizmasının olmaması

Bir JWT, kullanıcı oturumu kapatsa ya da bir yönetici hesabı devre dışı bıraksa bile süresi dolana kadar geçerli kalır. OWASP, token’ların temsil ettikleri oturumdan daha uzun yaşayabileceğine dikkat çeker.

  • Erişim token’larını kısa ömürlü tutun; ömürlerini gün değil, dakika cinsinden ölçün.
  • Sunucunun her kullanımda kontrol ettiği ve iptal edebildiği yenileme token’ları kullanın.
  • Oturum kapatma ve hesap askıya alma durumları için, OWASP’ın önerdiği gibi, token kimliklerinden (jti) oluşan bir engel listesini bu token’ların süresi dolana kadar tutun.
  • İmzalama anahtarlarını belirli bir takvimle değiştirin ve acil anahtar değişimi için test edilmiş bir süreciniz olsun.

Hata 7 - token’ları betiklerin okuyabileceği yerde saklamak

localStorage içinde tutulan token’lar sayfadaki her JavaScript tarafından okunabilir. OWASP HTML5 Security Cheat Sheet, tek bir siteler arası betik çalıştırma (XSS) açığının bu depolama nesnelerindeki her şeyi çalabileceği konusunda uyarır ve oturum tanımlayıcılarının burada tutulmamasını önerir.

Tarayıcı uygulamalarında, uygun bir SameSite ayarıyla birlikte HttpOnly ve Secure özellikli bir çerez, token’ı betiklerden uzak tutar. Çerezler siteler arası istek sahteciliğini (CSRF) de gündeme getirir; bunu da planlayın. Hangisini seçerseniz seçin, güçlü bir Content Security Policy XSS olasılığını en baştan azaltır.

Doğrulama kontrol listesi

  1. Kabul edilen algoritmaları sunucuda sabitleyin ve none değerini reddedin.
  2. Herhangi bir claim’i okumadan önce imzayı doğrulayan bir kütüphane kullanın.
  3. Her istekte exp, nbf, iss ve aud değerlerini doğrulayın.
  4. Token türlerini ayırmak için typ ya da farklı hedef alıcılar kullanın.
  5. Anahtarları sabit bir küme içinde kid ile arayın; anahtarları asla rastgele URL’lerden çekmeyin.
  6. En az 256 bitlik rastgele HMAC anahtarları ya da asimetrik anahtarlar kullanın.
  7. Payload’larda gizli bilgilere ve gereksiz kişisel verilere yer vermeyin.
  8. Erişim token’larını kısa ömürlü tutun ve iptali destekleyin.
  9. Tarayıcıdaki token’ları JavaScript’in erişemeyeceği yerde saklayın.

Nereden başlamalı

Test ortamınızdan bir token’ı JWT çözücümüze yapıştırarak tam olarak neleri açığa çıkardığını görün ve alg, aud ve exp değerlerini bu listeye göre kontrol edin. Canlı üretim token’larını hiçbir çevrim içi araca yapıştırmayın.

Kimlik doğrulama tasarımınız hakkında ikinci bir görüş ya da token işleme kodunuz için bir kod incelemesi istiyorsanız güvenli yazılım geliştirme ekibimiz yardımcı olabilir.

Nasıl yardımcı olabiliriz

Güvenli yazılım

Güvenliği yazılıma ilk satırdan itibaren yerleştirir, kendi güvenlik araçlarımızı da geliştiririz.

JWT çözücü

Bir JSON Web Token’ı çözün ve yaygın güvenlik hatalarına karşı kontrol edin; token tarayıcınızdan çıkmaz.

Bize yazın
AngelForce ekibi

Bu yazıyı AngelForce ekibi hazırladı: Avrupa ve Türkiye’deki kurumların sistemlerini test eden, izleyen ve koruyan; CEH, LPT Master ve CISA sertifikalı güvenlik danışmanları.

Aşağıda listelenen herkese açık kaynaklardan yapay zekâ desteğiyle yazıldı ve yayından önce AngelForce ekibi tarafından incelendi.

Kaynaklar

  1. datatracker.ietf.org/doc/html/rfc7519
  2. datatracker.ietf.org/doc/html/rfc8725
  3. datatracker.ietf.org/doc/html/rfc7518
  4. cheatsheetseries.owasp.org/cheatsheets/REST_Security_Cheat_Sheet.html
  5. cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html

Güvenli yazılım geliştirme hakkında yazılar

Neyi korumanız gerektiğini anlatın

Altyapınızı ve hedefinizi kısaca yazın, size e-postayla dönelim.

Bize yazın
info@angelforce.eu

AngelForce OÜ · Tallinn, Estonya