JWT (JSON Web Token) güvenlik en iyi pratikleri üzerine kapsamlı bir rehber. Doğrulama, depolama, imzalama algoritmaları ve global uygulamalardaki yaygın zafiyetlere karşı stratejiler.
JWT Token'ları: Global Uygulamalar İçin Güvenlikte En İyi Pratikler
JSON Web Token'ları (JWT'ler), iki taraf arasında talepleri (claims) güvenli bir şekilde temsil etmek için standart bir yöntem haline gelmiştir. Kompakt yapıları, kullanım kolaylıkları ve çeşitli platformlarda geniş destek görmeleri, onları modern web uygulamalarında, API'lerde ve mikroservislerde kimlik doğrulama ve yetkilendirme için popüler bir seçenek yapmıştır. Ancak, yaygın olarak benimsenmeleri aynı zamanda artan bir incelemeye ve çok sayıda güvenlik zafiyetinin keşfedilmesine yol açmıştır. Bu kapsamlı rehber, global uygulamalarınızın güvende kalmasını ve potansiyel saldırılara karşı dirençli olmasını sağlamak için JWT güvenlik en iyi pratiklerini incelemektedir.
JWT'ler Nedir ve Nasıl Çalışır?
Bir JWT, üç bölümden oluşan JSON tabanlı bir güvenlik token'ıdır:
- Başlık (Header): Token'ın türünü (JWT) ve kullanılan imzalama algoritmasını (örneğin, HMAC SHA256 veya RSA) belirtir.
- Veri Yükü (Payload): Bir varlık (genellikle kullanıcı) ve ek meta veriler hakkındaki ifadeler olan talepleri (claims) içerir. Talepler, kayıtlı (örneğin, issuer, subject, expiration time), genel (uygulama tarafından tanımlanan) veya özel (özel talepler) olabilir.
- İmza (Signature): Kodlanmış başlık, kodlanmış veri yükü, bir gizli anahtar (HMAC algoritmaları için) veya bir özel anahtar (RSA/ECDSA algoritmaları için), belirtilen algoritma ile birleştirilip imzalanarak oluşturulur.
Bu üç bölüm, Base64 URL formatında kodlanır ve noktalarla (.
) birleştirilerek nihai JWT dizesi oluşturulur. Bir kullanıcı kimliğini doğruladığında, sunucu bir JWT oluşturur; istemci bu token'ı (genellikle yerel depolamada veya bir çerezde) saklar ve sonraki isteklere dahil eder. Sunucu daha sonra isteği yetkilendirmek için JWT'yi doğrular.
Yaygın JWT Zafiyetlerini Anlamak
En iyi pratiklere geçmeden önce, JWT'ler ile ilişkili yaygın zafiyetleri anlamak kritik öneme sahiptir:
- Algoritma Karışıklığı: Saldırganlar,
alg
başlık parametresini güçlü bir asimetrik algoritmadan (RSA gibi) zayıf bir simetrik algoritmaya (HMAC gibi) değiştirme yeteneğini istismar eder. Eğer sunucu, HMAC algoritmasında genel anahtarı gizli anahtar olarak kullanırsa, saldırganlar sahte JWT'ler oluşturabilir. - Gizli Anahtarın İfşa Olması: JWT'leri imzalamak için kullanılan gizli anahtar ele geçirilirse, saldırganlar herhangi bir kullanıcıyı taklit ederek geçerli JWT'ler oluşturabilir. Bu durum, kod sızıntıları, güvensiz depolama veya uygulamanın diğer bölümlerindeki zafiyetler nedeniyle meydana gelebilir.
- Token Hırsızlığı (XSS/CSRF): JWT'ler güvensiz bir şekilde saklanırsa, saldırganlar bunları Siteler Arası Betik Çalıştırma (XSS) veya Siteler Arası İstek Sahteciliği (CSRF) saldırıları yoluyla çalabilir.
- Tekrar Oynatma Saldırıları (Replay Attacks): Saldırganlar, özellikle token'ların kullanım ömrü uzunsa ve özel karşı önlemler uygulanmamışsa, yetkisiz erişim elde etmek için geçerli JWT'leri yeniden kullanabilir.
- Doldurma Kehaneti Saldırıları (Padding Oracle Attacks): JWT'ler belirli algoritmalarla şifrelendiğinde ve doldurma (padding) işlemi yanlış yönetildiğinde, saldırganlar potansiyel olarak JWT'nin şifresini çözebilir ve içeriğine erişebilir.
- Saat Kayması Sorunları (Clock Skew Issues): Dağıtık sistemlerde, farklı sunucular arasındaki saat kayması, özellikle son kullanma tarihi (expiration) talepleriyle ilgili olarak JWT doğrulama hatalarına yol açabilir.
JWT Güvenliğinde En İyi Pratikler
JWT'ler ile ilişkili riskleri azaltmak için kapsamlı güvenlik en iyi pratikleri şunlardır:
1. Doğru İmzalama Algoritmasını Seçmek
İmzalama algoritması seçimi kritiktir. İşte dikkate alınması gerekenler:
alg: none
Kullanımından Kaçının: Aslaalg
başlığınınnone
olarak ayarlanmasına izin vermeyin. Bu, imza doğrulamasını devre dışı bırakır ve herkesin geçerli JWT'ler oluşturmasına olanak tanır. Birçok kütüphane bunu önlemek için yamalanmıştır, ancak kütüphanelerinizin güncel olduğundan emin olun.- Asimetrik Algoritmaları (RSA/ECDSA) Tercih Edin: Mümkün olduğunda RSA (RS256, RS384, RS512) veya ECDSA (ES256, ES384, ES512) algoritmalarını kullanın. Asimetrik algoritmalar imzalama için özel bir anahtar, doğrulama için ise genel bir anahtar kullanır. Bu, saldırganların genel anahtara erişseler bile sahte token'lar oluşturmasını engeller.
- Özel Anahtarları Güvenli Bir Şekilde Yönetin: Özel anahtarları, donanım güvenlik modülleri (HSM'ler) veya güvenli anahtar yönetim sistemleri kullanarak güvenli bir şekilde saklayın. Özel anahtarları asla kaynak kodu depolarına göndermeyin.
- Anahtarları Düzenli Olarak Döndürün (Rotate): İmzalama anahtarlarını düzenli olarak değiştirmek için bir anahtar döndürme stratejisi uygulayın. Bu, bir anahtarın ele geçirilmesi durumunda etkinin en aza indirilmesini sağlar. Genel anahtarlarınızı yayınlamak için JSON Web Key Sets (JWKS) kullanmayı düşünün.
Örnek: Anahtar Döndürme için JWKS Kullanımı
Bir JWKS uç noktası, JWT'leri doğrulamak için kullanılabilecek bir dizi genel anahtar sağlar. Sunucu anahtarları döndürebilir ve istemciler JWKS uç noktasını getirerek anahtar setlerini otomatik olarak güncelleyebilir.
/.well-known/jwks.json
:
{
"keys": [
{
"kty": "RSA",
"kid": "key1",
"alg": "RS256",
"n": "...",
"e": "AQAB"
},
{
"kty": "RSA",
"kid": "key2",
"alg": "RS256",
"n": "...",
"e": "AQAB"
}
]
}
2. JWT'leri Düzgün Bir Şekilde Doğrulamak
Düzgün doğrulama, saldırıları önlemek için esastır:
- İmzayı Doğrulayın: JWT imzasını her zaman doğru anahtar ve algoritma ile doğrulayın. JWT kütüphanenizin doğru yapılandırıldığından ve güncel olduğundan emin olun.
- Talepleri (Claims) Doğrulayın:
exp
(son kullanma zamanı),nbf
(önce değil),iss
(yayıncı) veaud
(hedef kitle) gibi temel talepleri doğrulayın. exp
Talebini Kontrol Edin: JWT'nin süresinin dolmadığından emin olun. Saldırganlar için fırsat penceresini en aza indirmek için makul bir token ömrü uygulayın.nbf
Talebini Kontrol Edin: JWT'nin geçerli başlangıç zamanından önce kullanılmadığından emin olun. Bu, token'ın kullanılması amaçlanan zamandan önce tekrar oynatma saldırılarını önler.iss
Talebini Kontrol Edin: JWT'nin güvenilir bir yayıncı tarafından yayınlandığını doğrulayın. Bu, yetkisiz taraflarca yayınlanan JWT'lerin kullanılmasını önler.aud
Talebini Kontrol Edin: JWT'nin uygulamanız için tasarlandığını doğrulayın. Bu, diğer uygulamalar için yayınlanan JWT'lerin sizinkine karşı kullanılmasını önler.- Reddetme Listesi Uygulayın (İsteğe Bağlı): Kritik uygulamalar için, ele geçirilmiş JWT'leri son kullanma sürelerinden önce geçersiz kılmak için bir reddetme listesi (iptal listesi olarak da bilinir) uygulamayı düşünün. Bu karmaşıklığı artırır ancak güvenliği önemli ölçüde artırabilir.
Örnek: Kodda Talepleri Doğrulama (Node.js ve jsonwebtoken
ile)
const jwt = require('jsonwebtoken');
try {
const decoded = jwt.verify(token, publicKey, {
algorithms: ['RS256'],
issuer: 'https://example.com',
audience: 'https://myapp.com'
});
console.log(decoded);
} catch (error) {
console.error('JWT doğrulaması başarısız oldu:', error);
}
3. İstemci Tarafında JWT'leri Güvenli Bir Şekilde Saklamak
JWT'lerin istemci tarafında nasıl saklandığı, güvenliği önemli ölçüde etkiler:
- Yerel Depolamadan (Local Storage) Kaçının: JWT'leri yerel depolamada saklamak, onları XSS saldırılarına karşı savunmasız hale getirir. Eğer bir saldırgan uygulamanıza JavaScript enjekte edebilirse, yerel depolamadan JWT'yi kolayca çalabilir.
- HTTP-Only Çerezleri Kullanın: JWT'leri
Secure
veSameSite
niteliklerine sahip HTTP-only çerezlerde saklayın. HTTP-only çerezlere JavaScript tarafından erişilemez, bu da XSS risklerini azaltır.Secure
niteliği, çerezin yalnızca HTTPS üzerinden iletilmesini sağlar.SameSite
niteliği, CSRF saldırılarını önlemeye yardımcı olur. - Yenileme Token'larını (Refresh Tokens) Düşünün: Bir yenileme token'ı mekanizması uygulayın. Kısa ömürlü erişim token'ları anlık yetkilendirme için kullanılırken, uzun ömürlü yenileme token'ları yeni erişim token'ları elde etmek için kullanılır. Yenileme token'larını güvenli bir şekilde saklayın (örneğin, şifreleme ile bir veritabanında).
- CSRF Koruması Uygulayın: Çerezleri kullanırken, senkronizasyon token'ları veya Double Submit Cookie deseni gibi CSRF koruma mekanizmalarını uygulayın.
Örnek: HTTP-Only Çerezleri Ayarlama (Node.js ve Express ile)
app.get('/login', (req, res) => {
// ... kimlik doğrulama mantığı ...
const token = jwt.sign({ userId: user.id }, privateKey, { expiresIn: '15m' });
const refreshToken = jwt.sign({ userId: user.id }, refreshPrivateKey, { expiresIn: '7d' });
res.cookie('accessToken', token, {
httpOnly: true,
secure: true, // Üretim ortamında true olarak ayarlayın
sameSite: 'strict', // veya ihtiyacınıza göre 'lax'
maxAge: 15 * 60 * 1000 // 15 dakika
});
res.cookie('refreshToken', refreshToken, {
httpOnly: true,
secure: true, // Üretim ortamında true olarak ayarlayın
sameSite: 'strict',
maxAge: 7 * 24 * 60 * 60 * 1000 // 7 gün
});
res.send({ message: 'Giriş başarılı' });
});
4. Algoritma Karışıklığı Saldırılarına Karşı Korunma
Algoritma karışıklığı kritik bir zafiyettir. İşte bunu nasıl önleyeceğiniz:
- İzin Verilen Algoritmaları Açıkça Belirtin: JWT'leri doğrularken, izin verilen imzalama algoritmalarını açıkça belirtin. Algoritmayı otomatik olarak belirlemesi için JWT kütüphanesine güvenmeyin.
alg
Başlığına Güvenmeyin: JWT'dekialg
başlığına asla körü körüne güvenmeyin. Her zaman önceden tanımlanmış izin verilen algoritmalar listesine karşı doğrulayın.- Güçlü Statik Tipleme Kullanın (Mümkünse): Statik tiplemeyi destekleyen dillerde, anahtar ve algoritma parametreleri için katı tip denetimi uygulayın.
Örnek: Algoritma Karışıklığını Önleme (Node.js ve jsonwebtoken
ile)
const jwt = require('jsonwebtoken');
try {
const decoded = jwt.verify(token, publicKey, {
algorithms: ['RS256'] // Yalnızca RS256'ya açıkça izin ver
});
console.log(decoded);
} catch (error) {
console.error('JWT doğrulaması başarısız oldu:', error);
}
5. Uygun Token Süre Sonu ve Yenileme Mekanizmalarını Uygulama
Token ömrü, önemli bir güvenlik konusudur:
- Kısa Ömürlü Erişim Token'ları Kullanın: Erişim token'larını kısa ömürlü tutun (örneğin, 5-30 dakika). Bu, bir token ele geçirildiğinde etkiyi sınırlar.
- Yenileme Token'ları Uygulayın: Kullanıcının yeniden kimlik doğrulaması gerekmeden yeni erişim token'ları elde etmek için yenileme token'ları kullanın. Yenileme token'larının ömrü daha uzun olabilir ancak güvenli bir şekilde saklanmalıdır.
- Yenileme Token'ı Döndürme (Rotation) Uygulayın: Her yeni erişim token'ı verildiğinde yenileme token'larını döndürün. Bu, eski yenileme token'ını geçersiz kılarak, bir yenileme token'ının ele geçirilmesi durumunda potansiyel hasarı sınırlar.
- Oturum Yönetimini Düşünün: Hassas uygulamalar için, JWT'lere ek olarak sunucu taraflı oturum yönetimi uygulamayı düşünün. Bu, erişimi daha ayrıntılı bir şekilde iptal etmenize olanak tanır.
6. Token Hırsızlığına Karşı Korunma
Token hırsızlığını önlemek çok önemlidir:
- Katı İçerik Güvenliği Politikası (CSP) Uygulayın: XSS saldırılarını önlemek için CSP kullanın. CSP, web sitenizde hangi kaynakların (betikler, stiller, resimler vb.) yüklenmesine izin verildiğini belirtmenizi sağlar.
- Kullanıcı Girdisini Temizleyin (Sanitize): XSS saldırılarını önlemek için tüm kullanıcı girdilerini temizleyin. Potansiyel olarak kötü amaçlı karakterlerden kaçmak için güvenilir bir HTML temizleyici kütüphanesi kullanın.
- HTTPS Kullanın: İstemci ve sunucu arasındaki iletişimi şifrelemek için her zaman HTTPS kullanın. Bu, saldırganların ağ trafiğini dinleyerek JWT'leri çalmasını önler.
- HSTS (HTTP Strict Transport Security) Uygulayın: Tarayıcılara web sitenizle iletişim kurarken her zaman HTTPS kullanmaları talimatını vermek için HSTS kullanın.
7. İzleme ve Günlük Kaydı
Etkili izleme ve günlük kaydı, güvenlik olaylarını tespit etmek ve müdahale etmek için esastır:
- JWT Yayınlama ve Doğrulamasını Günlüğe Kaydedin: Kullanıcı ID'si, IP adresi ve zaman damgası dahil olmak üzere tüm JWT yayınlama ve doğrulama olaylarını günlüğe kaydedin.
- Şüpheli Aktiviteleri İzleyin: Birden çok başarısız giriş denemesi, farklı konumlardan aynı anda kullanılan JWT'ler veya hızlı token yenileme istekleri gibi olağandışı desenleri izleyin.
- Alarmlar Kurun: Potansiyel güvenlik olayları hakkında sizi bilgilendirmek için alarmlar kurun.
- Günlükleri Düzenli Olarak Gözden Geçirin: Şüpheli aktiviteleri belirlemek ve araştırmak için günlükleri düzenli olarak gözden geçirin.
8. Hız Sınırlama (Rate Limiting)
Kaba kuvvet (brute-force) ve hizmet reddi (DoS) saldırılarını önlemek için hız sınırlaması uygulayın:
- Giriş Denemelerini Sınırlayın: Tek bir IP adresinden veya kullanıcı hesabından gelen başarısız giriş denemelerinin sayısını sınırlayın.
- Token Yenileme İsteklerini Sınırlayın: Tek bir IP adresinden veya kullanıcı hesabından gelen token yenileme isteklerinin sayısını sınırlayın.
- API İsteklerini Sınırlayın: Tek bir IP adresinden veya kullanıcı hesabından gelen API isteklerinin sayısını sınırlayın.
9. Güncel Kalmak
- Kütüphaneleri Güncel Tutun: Güvenlik zafiyetlerini yamamak için JWT kütüphanelerinizi ve bağımlılıklarınızı düzenli olarak güncelleyin.
- Güvenlikteki En İyi Pratikleri Takip Edin: JWT'lerle ilgili en son güvenlik en iyi pratikleri ve zafiyetler hakkında bilgi sahibi olun.
- Güvenlik Denetimleri Gerçekleştirin: Potansiyel zafiyetleri belirlemek ve gidermek için uygulamanızın güvenlik denetimlerini düzenli olarak yapın.
JWT Güvenliği İçin Global Hususlar
Global uygulamalar için JWT'leri uygularken aşağıdakileri göz önünde bulundurun:
- Zaman Dilimleri: Sunucularınızın, özellikle
exp
venbf
taleplerini etkileyebilecek saat kayması sorunlarından kaçınmak için güvenilir bir zaman kaynağına (örneğin, NTP) senkronize olduğundan emin olun. Tutarlı bir şekilde UTC zaman damgalarını kullanmayı düşünün. - Veri Gizliliği Yönetmelikleri: GDPR, CCPA ve diğerleri gibi veri gizliliği yönetmeliklerine dikkat edin. JWT'lerde saklanan kişisel veri miktarını en aza indirin ve ilgili yönetmeliklere uyumu sağlayın. Gerekirse hassas talepleri şifreleyin.
- Uluslararasılaştırma (i18n): JWT taleplerinden gelen bilgileri görüntülerken, verilerin kullanıcının dili ve bölgesi için uygun şekilde yerelleştirildiğinden emin olun. Bu, tarihlerin, sayıların ve para birimlerinin uygun şekilde biçimlendirilmesini içerir.
- Yasal Uyumluluk: Farklı ülkelerdeki veri depolama ve iletimi ile ilgili yasal gerekliliklerin farkında olun. JWT uygulamanızın geçerli tüm yasa ve yönetmeliklere uygun olduğundan emin olun.
- Çapraz Kökenli Kaynak Paylaşımı (CORS): Uygulamanızın farklı alan adlarındaki kaynaklara erişmesine izin vermek için CORS'u doğru şekilde yapılandırın. Bu, özellikle farklı hizmetler veya uygulamalar arasında kimlik doğrulama için JWT'ler kullanıldığında önemlidir.
Sonuç
JWT'ler, kimlik doğrulama ve yetkilendirmeyi yönetmek için kullanışlı ve verimli bir yol sunar, ancak aynı zamanda potansiyel güvenlik riskleri de içerirler. Bu en iyi pratikleri takip ederek, zafiyet riskini önemli ölçüde azaltabilir ve global uygulamalarınızın güvenliğini sağlayabilirsiniz. En son güvenlik tehditleri hakkında bilgi sahibi olmayı ve uygulamanızı buna göre güncellemeyi unutmayın. JWT yaşam döngüsü boyunca güvenliğe öncelik vermek, kullanıcılarınızı ve verilerinizi yetkisiz erişimden korumaya yardımcı olacaktır.