JWT

JWT Nedir?

JSON Web Token'ları (JWT), sistemler arasında kriptografik olarak imzalanmış JSON verilerinin gönderilmesi için standartlaştırılmış bir formattır. Teorik olarak her türlü veriyi içerebilirler, ancak en yaygın olarak kimlik doğrulama, oturum işleme ve erişim kontrol mekanizmalarının bir parçası olarak kullanıcılar hakkında bilgi göndermek için kullanılırlar.

Klasik session token'ların aksine, bir sunucunun ihtiyaç duyduğu tüm veriler JWT'nin kendi içinde client-side olarak saklanır. Bu, JWT'leri kullanıcıların birden fazla arka uç sunucusuyla sorunsuz bir şekilde etkileşime girmesi gereken yüksek oranda dağıtılmış web siteleri için popüler bir seçim haline getirir.

JWT saldırıları, bir kullanıcının kötü niyetli bir hedefe ulaşmak için sunucuya değiştirilmiş JWT'ler göndermesini içerir. Genellikle bu amaç, kimliği zaten doğrulanmış olan başka bir kullanıcının taklit edilmesi yoluyla kimlik doğrulama ve erişim kontrollerini atlamaktır.

Nasıl Test Edilir?

Doğrudan Verileri Değiştir

Eğer anahtar kontrolü yapılmıyorsa jwt içindeki verileri değiştirmeyi deneyebiliriz.

Algoritma Değiştir

Algoritmayı none yaparak verileri değiştirmeyi deneyebiliriz.

Zayıf Anahtar (HS256)

Jwt-List: https://github.com/wallarm/jwt-secrets/blob/master/jwt.secrets.list

hashcat -a 0 -m 16500 <JWT> jwt.secrets.list

JWK Header Injection (RS256)

Embedded JWK saldırısı deneyebiliriz. Extension'da var.

JKU Header Injection (RS256)

Embed Collaborator Payload ile jku header ekliyoruz. Sonrasında bir RSA key oluşturuyoruz. Burada oluşan keyi aşağıdaki şekilde bir dosyada paylaşıyoruz.

{
    "keys": [
        {
           <PAYLOAD>
        }
    ]
}

Sonrasında bu dosyanın adresini jku başlığına yazıyoruz. Son olarak anahtar ile JWT'yi imzalıyoruz.

KID Header Path Traversal (HS256)

Öncelikle simetrik bir anahtar oluştuyoruz ve k değerini AA== yapıyoruz.

Sonrasında JWT'nin kid değerini aşağıdaki değerlerden biri yapıyoruz ve JWT'yi oluşturduğumuz anahtar ile imzalıyoruz.

/dev/null
../../../dev/null

Public Key ile Algorithm Confusion (RS256)

Öncelikle sunucunun public key değerini bulmamız gerek. Bunun için /jwks.json dizinine bakabiliriz.

Sonrasında burdaki değerler ile bir RSA key oluşturuyoruz ve PEM olarak kopyalıyoruz.

Şimdi bir simetrik key oluşturuyoruz ve k değerinine PEM değerinin base64 halini yazıyoruz.

Sonrasında JWT'yi bu simetrik key ile alg değerini değiştirerek imzalıyoruz.

Public Key Olmadan Algorithm Confusion (RS256)

Bu yöntem için bir kullanıcıya iki kere giriş yapıyoruz ve iki farklı JWT alıyoruz ve komutu çalıştırıyoruz.

docker run --rm -it portswigger/sig2n <token_1> <token_2>

Çıkan Tampered JWT'leri teker teker deniyoruz. Eğer çalışırsa onun üstündeki x509 anahtarını alıyoruz ve simetrik anahtar olarak keydediyoruz.

Bu anahtar ile JWT'yi imzalayabiliriz.

Otomatize Araçlar

Burp Extension: https://github.com/portswigger/json-web-tokens

JWT Tool: https://github.com/ticarpi/jwt_tool

python3 jwt_tool.py -M at \
    -t "https://example.com/" \
    -rh "Authorization: Bearer <JWT>" \
    -rc "session=<JWT>"

Kaynaklar

Portswigger: https://portswigger.net/web-security/jwt

Last updated