IT
OmnvertGörsel • Belge • Ağ

JWT token inceleme: çözmek doğrulamak değildir

5 dakika okuma
Bir editörde renklendirilmiş kaynak kodu gösteren dizüstü ekranı; ekrana pencere çerçeveleri yansıyor.

Bir JWT imzalıdır, şifreli değildir: yükünü tokenı gören herkes okur. Süresi dolmamış bir token da parola kadar canlı bir kimlik bilgisidir.

Bir JWT neyden oluşur

Kompakt biçimdeki bir JWT, noktayla ayrılmış üç parçadır: header.payload.signature. İlk iki parça JSON'dur ve base64url ile kodlanmıştır; üçüncüsü ilk ikisinin üzerine atılmış imzadır. Kodlamanın base64url olması ayrıntı değil, kuraldır: standart base64'ün + ve / karakterleri yerine - ve _ kullanılır ve sondaki = dolgusu atılır. Böylece token bir URL'de veya başlıkta kaçış gerektirmeden taşınabilir. Bir tokenı standart base64 çözücüye verip hata almanızın sebebi genelde budur.

İmza, tam olarak base64url(header) + "." + base64url(payload) dizesinin üzerine hesaplanır. Yani bir karakterini bile değiştirdiğinizde imza tutmaz. Buradan çıkan sonuç önemlidir: token kurcalamaya karşı korunur, ama okunmaya karşı korunmaz.

Çözmek ile doğrulamak aynı şey değil

Bir tokenı çözmek base64url'den geri dönmektir; anahtar gerektirmez, imzaya bakmaz, süreyi kontrol etmez. Doğrulamak ise imzayı yeniden hesaplayıp karşılaştırmak, algoritmanın beklediğiniz algoritma olduğunu teyit etmek ve zaman ile hedef kitle iddialarını kontrol etmektir. Hata ayıklarken bu ikisini karıştırmak yaygın ve pahalıdır: ekranda düzgün bir JSON görmek, tokenın geçerli olduğunu göstermez.

Tam bir doğrulama şu adımları içerir: imzanın anahtarla tutması, alg değerinin sunucunun izin verdiği listede olması, iss ve aud alanlarının beklenen değerlerle eşleşmesi, exp ve nbf alanlarının geçerli olması. Bunlardan biri atlandığında token geçerli görünür ama güvenli değildir.

Başlıkta iki alan öne çıkar. alg imzanın nasıl hesaplandığını, kid ise hangi anahtarın kullanıldığını söyler. İkisi de tokenın kendisinden gelir, yani saldırganın kontrolündedir. Bir doğrulayıcının bu alanlara körü körüne güvenmesi klasik hataların kaynağıdır.

  • none algoritması. Spesifikasyon imzasız bir JWS biçimi tanımlar: alg değerini none yapıp imza bölümünü boş bırakırsınız. Doğrulayıcı başlıktaki değere uyarsa imzayı hiç kontrol etmeden tokenı kabul eder. Çözüm, kabul edilen algoritmaları sunucu tarafında sabit bir listeyle sınırlamaktır.
  • Algoritma karışıklığı. Sistem RS256 bekliyorsa doğrulayıcı açık anahtarla imzayı kontrol eder. Saldırgan alg değerini HS256 yapar ve tokenı, herkese açık olan aynı açık anahtarı HMAC gizli anahtarı gibi kullanarak imzalar. Kütüphane algoritmayı tokendan okuyup anahtarı ham bayt dizisi olarak alırsa imza tutar. Beklenen algoritmayı çağıran taraf belirtmelidir.
  • kid üzerinden yönlendirme. kid doğrudan bir dosya yoluna veya SQL sorgusuna gidiyorsa, yol geçişi ve enjeksiyon için hazır bir giriştir. Anahtar kimliğini yalnızca bilinen anahtarlar kümesinde arayın.
  • Tokendan gelen anahtar kaynağı. jwk ve jku başlıkları anahtarı ya da anahtarın adresini tokenın içine koyar. Kendi kendini doğrulayan bir token elde etmemek için bunlar ya kapalı olmalı ya da sıkı bir beyaz listeyle sınırlanmalıdır.

Yük içine ne konur, ne konmaz

Bir JWT imzalıdır, şifreli değildir. Payload bölümünü tokenı gören herkes okuyabilir: tarayıcı eklentisi, ara vekil sunucu, günlük dosyası, hata izleme servisi. JWE ile şifreli bir token üretmek mümkündür ama gündelik kullanımdaki tokenların neredeyse tamamı düz imzalı JWS'tir. Bu yüzden içerik seçimi bir gizlilik kararıdır.

  • Uygun: kullanıcı kimliği (dahili ve anlamsız bir tanımlayıcı), rol veya yetki adları, kiracı kimliği, oturum kimliği, süre alanları.
  • Uygun değil: parola veya parola özeti, kimlik numarası, tam adres, sağlık ve finans verisi, API gizli anahtarları, başka bir sistemin erişim tokenı.

Standart alanlar küçük bir kümedir ve hepsinin bir işi vardır: iss tokenı kimin ürettiği, sub kimin hakkında olduğu, aud kimin kabul etmesi gerektiği, exp bitiş, nbf başlangıç, iat üretim anı, jti tekrar kullanımı yakalamak için benzersiz kimlik. jti için çakışma ihtimali düşük bir değer gerekir; UUID ve ULID üreticisi bunun için yeterlidir.

Bir de boyut meselesi var. Token her istekte gider ve yetki listesi büyüdükçe başlık boyutu büyür; bazı ters vekil sunucular birkaç kilobaytın üzerindeki başlıkları reddeder. Yetkiyi tokena gömmek ile sunucuda aramak arasındaki tercih, aynı zamanda iptal edilebilirlik tercihidir.

Süre, saat kayması ve iptal

exp, nbf ve iat saniye cinsinden Unix zaman damgalarıdır, milisaniye değil. Çoğu "token daha geçerli olmamalıydı" hatası bu birim karışıklığından çıkar. Ham değerleri okunur tarihe çevirmek için zaman damgası dönüştürücü işinizi görür.

Sunucu saatleri birbirini tutmaz. Üreten ile doğrulayan arasında birkaç saniyelik fark, sınırdaki tokenları rastgele reddettirir. Bu yüzden doğrulayıcılar küçük bir tolerans tanır; genelde otuz saniyeden fazlası gerekmez ve tolerans, kısa ömrü anlamsızlaştıracak kadar büyük olmamalıdır.

Asıl mesele iptaldir. İmzalı bir token, süresi dolana kadar kendi başına geçerlidir; kullanıcıyı sildiğinizde ya da yetkisini aldığınızda o token çalışmaya devam eder. Pratik çözüm erişim tokenını kısa tutmak (dakikalar mertebesinde), yenileme tokenını sunucuda saklamak ve acil durumlar için jti üzerinden bir kara liste tutmaktır.

Koyu bir zeminde duran küçük bir metal anahtar demeti; siyah beyaz çekilmiş.
Bir imza, arkasındaki anahtar kadar değerlidir. Canlı bir tokenı başkasının çözücüsüne yapıştırmak, anahtarın koruduğu şeyi doğrudan teslim etmektir.

Tokenı güvenle incelemek

Süresi dolmamış bir token, parola kadar canlı bir kimlik bilgisidir. Onu görüntüleyen herkes, süresi bitene kadar o kullanıcı gibi davranabilir. Üretim tokenlarını rastgele bir çevrim içi çözücüye yapıştırmak, parolayı yapıştırmaktan farklı değildir.

  • Hata ayıklarken test ortamından alınmış, kısa ömürlü bir token kullanın.
  • Mecbur kaldıysanız işiniz bittiğinde oturumu sonlandırın ve tokenı geçersiz kılın.
  • Gizli anahtarı, tokenı yapıştırdığınız aracın girdisine yazmayın; imza doğrulaması gerekiyorsa açık anahtar veya JWKS ile çalışın.
  • Tokenı hata kaydına, ekran görüntüsüne ve destek biletine yapıştırmayın; bunlar aranabilir arşivlerdir.

Bu koşulları karşılayan bir araç kullanın. JWT çözümleyici ve doğrulayıcı tokenı tarayıcıda çözer, imzayı tarayıcının WebCrypto arayüzüyle doğrular ve token bir sunucuya gönderilmez; tek isteğe bağlı ağ isteği, siz bir JWKS adresi girdiğinizde o adrese yapılan istektir. Çözülmüş yükü daha rahat okumak için JSON görüntüleyici kullanabilirsiniz.

Uygulama tarafı kontrol listesi

  1. Kabul edilen algoritmaları sunucuda sabit bir listeyle sınırlayın; none asla listede olmasın.
  2. Beklenen algoritmayı doğrulama çağrısında açıkça belirtin, tokendan okumayın.
  3. iss ve aud değerlerini kontrol edin; aksi halde başka bir servis için üretilmiş geçerli bir token sizde de çalışır.
  4. exp ve nbf kontrolünü küçük bir toleransla yapın.
  5. Anahtarları JWKS üzerinden dağıtın, kid ile yalnızca bilinen kümede arama yapın ve anahtar döndürmeyi baştan planlayın.
  6. Tokenı yalnızca TLS üzerinden taşıyın. Sunucu tarafını TLS kontrolüyle doğrulayın.
  7. Hassas veriyi yükün dışında tutun ve tokenı kısa ömürlü yapın.

Aynı ilke başka yerlerde de karşınıza çıkar. Bir ağ yakalamasından çıkardığınız yetkilendirme başlığını incelerken pcap okuma yazısındaki gizlilik uyarıları geçerlidir; bir dosyanın başlıklarını okumakla onu güvenli ilan etmek arasındaki fark ise EXE incelemesi yazısında aynı biçimde durur.

Sık sorulanlar

JWT şifreli mi?

Hayır. Yaygın kullanımdaki JWT imzalıdır (JWS): içerik kurcalamaya karşı korunur ama okunmaya karşı korunmaz. Payload'ı base64url'den çözen herkes görür. Şifreli token için JWE gerekir, o da ayrı bir yapıdır ve gündelik oturum tokenlarında nadiren kullanılır.

Tokenı çözdüm ve JSON düzgün görünüyor, geçerli mi?

Bu bilgi yeterli değil. Çözme işlemi imzaya bakmaz, algoritmayı kontrol etmez, süreyi denetlemez. Geçerlilik için imzanın anahtarla tutması, alg değerinin izin verilen listede olması, iss ve aud eşleşmesi ve exp ile nbf kontrolü gerekir.

none algoritması ne demek?

Spesifikasyon imzasız bir JWS biçimi tanımlar: alg alanı none olur ve imza bölümü boş bırakılır. Doğrulayıcı algoritmayı tokenın kendisinden okuyorsa böyle bir tokenı imzasız kabul edebilir. Korunma yolu, kabul edilen algoritmaları sunucu tarafında sabitlemektir.

Süresi dolmuş bir tokenı iptal etmem gerekir mi?

Süresi dolmuş token zaten reddedilir. Sorun, süresi dolmamış tokenlardır: imzalı token kendi başına geçerlidir ve kullanıcıyı sildiğinizde bile süresi bitene kadar çalışır. Bu yüzden erişim tokenları dakikalar mertebesinde tutulur ve acil iptal için jti üzerinden kara liste kullanılır.

Üretim tokenını çevrim içi bir çözücüye yapıştırmakta sakınca var mı?

Var. Süresi dolmamış bir token canlı kimlik bilgisidir; onu gören taraf o kullanıcı gibi davranabilir. Test ortamından kısa ömürlü bir token kullanın, gizli anahtarı hiçbir çevrim içi forma girmeyin ve mecbur kaldıysanız işiniz bitince oturumu sonlandırın.

Yazıda kullanılan araçlar

Kaynaklar

YöntemGörsel kaynakları