JWT do hloubky: bezpečnost tokenů, zranitelnosti a nejlepší postupy
JSON Web Tokeny (JWT) jsou de facto standardem pro bezstavovou autentizaci v moderních webových aplikacích. Jejich flexibilita ovšem často vede k fatálním chybám v konfiguraci. Když pentester uvidí JWT, nevidí jen identifikátor relace – vidí kryptografický útočný povrch.
Klíčové poznatky
- JWT je zakódovaný, nikoli zašifrovaný – každý claim v payloadu si může přečíst kdokoli, kdo token drží.
- Záměna algoritmů (RS256 za HS256) a algoritmus
nonezůstávají nejzávažnějšími chybami podpisu, na které narážíme ve vlastních a starších implementacích. - Klíče pro HS256 jsou hesla. Zachycený token lze prolomit offline nástrojem Hashcat, bez jediné další interakce s cílem.
- Parametry hlavičky dodané klientem, jako
kidajku, mění ověřování podpisu v prostor pro injektáž. - Platný podpis neříká nic o platnosti claimů –
exp,issaaudje nutné vynucovat při každém požadavku. - Access tokeny držte v paměti a refresh tokeny v cookies s příznaky
HttpOnly,SecureaSameSite– nikdy ne vlocalStorage.
Anatomie JWT: hlavička, payload a podpis
JWT se skládá ze tří částí: hlavičky, payloadu a
podpisu, které jsou od sebe oddělené tečkou (.). Pro pentestera
vypadá zachycený JWT jako dlouhý řetězec zdánlivě náhodných znaků. Zde je příklad z reálného
provozu:
eyJraWQiOiI5MTM2ZGRiMy1jYjBhLTRhMTktYTA3ZS1lYWRmNWE0NGM4YjUiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTY0ODAzNzE2NCwibmFtZSI6IkNhcmxvcyBNb250b3lhIiwic3ViIjoiY2FybG9zIiwicm9sZSI6ImJsb2dfYXV0aG9yIiwiZW1haWwiOiJjYXJsb3NAY2FybG9zLW1vbnRveWEubmV0IiwiaWF0IjoxNTE2MjM5MDIyfQ.SYZBPIBg2CRjXAJ8vCER0LA_ENjII1JakvNQoP-Hw6GG1zfl4JyngsZReIfqRvIAEi5L4HV0q7_9qGhQZvy9ZdxEJbwTxRs_6Lb-fZTDpW6lKYNdMyjw45_alSCZ1fypsMWz_2mTpQzil0lOtps5Ei_z7mM7M8gCwe_AGpI53JxduQOaB5HkT5gVrv9cKu9CsW5MS6ZbqYXpGyOG5ehoxqm8DL5tFYaW3lB50ELxi0KsuTKEbD0t5BCl0aCR2MBJWAbN-xeLwEenaqBiwPVvKixYleeDQiBEIylFdNNIMviKRgXiYuAvMziVPbwSgkZVHeEdF5MQP1Oe2Spac-6IfA
Hlavička a payload jsou pouze JSON objekty zakódované pomocí Base64Url. Jsou tedy jen zakódované, nikoli zašifrované. Kdokoli, kdo se k tokenu dostane, si tato data může dekódovat a přečíst.
Vizualizace struktury JWT
JWT (technicky vzato JWS – tedy JSON Web Token „when signed“, ve chvíli, kdy je podepsaný) se
skládá ze tří částí oddělených tečkou: Header.Payload.Signature.
{ "alg": "HS256", "typ": "JWT" }
{ "sub": "andrej", "role": "hacker" }
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
"secret"
) = MmM0ZGMxM2Y1NWQ2YTY2YTE
Hlavička
Hlavička obsahuje metadata o samotném tokenu, především jeho typ a kryptografický algoritmus použitý k jeho zabezpečení. Dekódování první části výše uvedeného tokenu odhalí:
{
"kid": "9136ddb3-cb0a-4a19-a07e-eadf5a44c8b5",
"alg": "RS256"
}
Payload
Payload obsahuje samotné „claimy“, tedy tvrzení o uživateli. Právě ten je hlavním cílem manipulace během bezpečnostního testu. Dekódování prostřední části našeho příkladu odhalí:
{
"iss": "portswigger",
"exp": 1648037164,
"name": "Andrej Šebeň",
"sub": "andrej",
"role": "pentester",
"email": "[email protected]",
"iat": 1516239022
}
Podpis
Protože si hlavičku i payload může kdokoli snadno přečíst nebo je upravit, stojí bezpečnost jakéhokoli mechanismu založeného na JWT především na kryptografickém podpisu.
Server, který token vydává, vytvoří pomocí tajného podpisového klíče hash z hlavičky a payloadu zakódovaných v Base64Url. Tento mechanismus zaručuje dvě věci:
- Protože je podpis přímo odvozen od zbytku tokenu, změna jediného bajtu v hlavičce nebo payloadu vede k nesouhlasícímu podpisu.
- Bez znalosti tajného podpisového klíče serveru by nemělo být možné vygenerovat správný podpis pro podvrženou hlavičku nebo payload.
Co hackeři v JWT hledají
Protože jsou JWT ze své podstaty čitelné, útočníci je nevnímají jako šifrovaná data, ale jako cenný zdroj informací pro průzkum. Z pohledu útočníka bývají logické chyby nejčastěji právě v payloadu. Tyto klíčové claimy kontrolujeme okamžitě:
| Claim | Účel | Co ověřuje pentest |
|---|---|---|
iss (Issuer) |
Určuje, kdo token vydal. | Ověřuje to backend doopravdy? Systém, který přijímá tokeny vydané neoprávněnou třetí stranou, je zranitelný vůči záměně tokenů. |
sub (Subject) |
Uživatel nebo entita, kterou token reprezentuje, často ID uživatele. | Insecure Direct Object Reference (IDOR). Můžeme hodnotu změnit na
admin nebo user_id=1 a obejít tak autorizaci? |
aud (Audience) |
Určuje zamýšleného příjemce. | Lze token vydaný pro jednu mikroslužbu přehrát vůči úplně jiné, vysoce privilegované mikroslužbě? |
exp (Expiration Time) |
Unixové časové razítko, kdy platnost tokenu vyprší. | Vynucuje to server doopravdy? Pravidelně nacházíme API, která přijímají prošlé tokeny donekonečna. |
nbf (Not Before) |
Čas, před kterým token nesmí být přijat. | Ve validační logice bývá často zcela opomenut. |
iat (Issued At) |
Kdy byl token vytvořen. | Užitečné pro výpočet životnosti tokenů a odhalení tokenů, které se nikdy nerotují. |
Průzkum payloadu: zlatý důl informací
Protože je payload viditelný pro každého, kdo token drží, měli by ho vývojáři považovat za veřejnou informaci. Při testech pravidelně nacházíme zbytečné interní detaily vystavené prostřednictvím vlastních claimů:
- Mapování interní sítě: vlastní claimy jako
"node_ip": "10.0.4.12","cluster": "prod-us-east-1a"nebo"db_host": "internal-db.local"prozrazují architekturu interní sítě a rozsahy IP adres. - Únik informací o frameworku a poskytovateli identity: konvence pojmenování
claimů odhalují použitý technologický stack. Claimy jako
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/namesignalizují backend postavený na Microsoft .NET / Entra ID, což nám umožňuje cílit na zranitelnosti specifické pro daný stack. - Osobní údaje (PII): zbytečné vystavení e-mailů, telefonních čísel, celých jmen nebo adres uživatelů – což okamžitě zakládá porušení předpisů (GDPR / CCPA).
- Enumerace tenantů a rolí: claimy jako
"tenant_id": "uuid","is_god_mode": falsenebo"permissions": ["read:profile"]odhalují autorizační schéma a dávají nám přesné názvy parametrů, na které lze cílit při eskalaci oprávnění.
Příklad děravého JWT payloadu zachyceného v reálném provozu:
{
"iss": "auth.internal-corp.local",
"sub": "usr_99812",
"email": "[email protected]",
"role": "admin",
"internal_ip": "10.240.12.88",
"db_shard": "shard-04-eu",
"is_admin": true,
"exp": 1748037164
}
Bearer tokeny vs. refresh tokeny: architektura a ukládání
Bezpečná implementace JWT stojí na dvoutokenovém systému: krátkodobých access tokenech (bearer tokenech) a dlouhodobých refresh tokenech. Jejich nesprávné ukládání je vůbec nejčastější zranitelnost, kterou reportujeme.
Bearer tokeny (access tokeny)
- Access tokeny autorizují požadavky na API a jsou záměrně krátkodobé, obvykle s platností 5 až 15 minut.
- Ukládejte je výhradně do paměti aplikace. Vyhněte se
localStorageasessionStorage, protože jakákoli úspěšně zneužitá XSS zranitelnost je může útočníkovi vyzradit.
Refresh tokeny
- Refresh tokeny slouží výhradně k získání nových access tokenů po vypršení jejich platnosti.
- Měly by být uložené v cookies s příznaky
HttpOnly,SecureaSameSite, což znemožní přístup z JavaScriptu a výrazně sníží riziko krádeže tokenu přes XSS, přičemž zároveň pomáhá zmírnit CSRF.
Příručka pentestera: nejčastější útoky na JWT
Při auditu webové aplikace procházejí týmy penetračních testerů obvykle následující vektory útoku.
A. Selhání validace podpisu
Řada zranitelností JWT nevzniká kvůli prolomené kryptografii, ale kvůli nesprávnému ověřování
podpisu. Historicky některé knihovny akceptovaly algoritmus none, což útočníkům
umožňovalo podpis zcela odstranit a přitom volně měnit claimy, například role uživatele.
Všechny hlavní moderní knihovny none ve výchozím nastavení odmítají, tato chyba se
ale stále objevuje ve starších aplikacích a ve vlastních implementacích JWT – a kdykoli
narazíte na nestandardní stack, stojí za otestování.
Další klasikou je záměna algoritmů (algorithm confusion). Jde o jednu z nejzávažnějších zranitelností JWT a vyplatí se jí rozumět přesně.
- RS256 je asymetrický algoritmus. Server podepisuje tokeny svým
privátním klíčem a ověřuje je odpovídajícím veřejným
klíčem. Veřejný klíč bývá volně dostupný – například vystavený na endpointu
/.well-known/jwks.json. - HS256 je symetrický algoritmus. Server používá k podepisování i ověřování tokenů jediný sdílený tajný klíč.
Útok zneužívá situaci, kdy server akceptuje oba algoritmy, aniž by měl explicitně natvrdo dané, který z nich očekává:
- Útočník získá veřejný klíč serveru, často zcela triviálně z JWKS endpointu.
- Upraví payload tokenu – například povýší
"role": "user"na"role": "admin". - Změní hlavičku z
"alg": "RS256"na"alg": "HS256". - Znovu podepíše celý upravený token (hlavičku i payload), přičemž jako tajný klíč pro HS256 použije veřejný klíč.
- Server token přijme, uvidí
alg: HS256a ověří ho pomocí veřejného klíče jako HMAC klíče. Podpis sedí a podvržený token je akceptován.
Příčinou není prolomená kryptografie – je jí server, který slepě věří hlavičce alg
dodané klientem a nechá ji rozhodovat o tom, jak se má token ověřit. Za normálních
okolností by změna alg v hlavičce podpis znehodnotila, protože podpis pokrývá jak
hlavičku, tak payload. Útočník ale celý upravený token podepíše znovu, takže nový podpis je pod
změněným algoritmem naprosto platný.
Moderní knihovny tyto chyby z velké části odstranily, stále se ale objevují ve starších aplikacích a ve vlastních implementacích JWT.
B. Slabé podpisové klíče
Aplikace používající symetrické algoritmy, jako je HS256, jsou bezpečné jen do té
míry, do jaké je bezpečný tajný klíč použitý k podepsání tokenu.
Během penetračního testu lze zachycený JWT napadnout kompletně offline pomocí nástrojů jako Hashcat nebo John the Ripper. Slabé klíče typu názvů firem, slovníkových slov nebo předvídatelných frází bývají prolomeny během několika minut. Útočník pak dokáže generovat platné tokeny pro libovolného uživatele, aniž by s cílovou aplikací musel znovu jakkoli komunikovat.
C. Injektáž parametrů hlavičky
Hlavičky JWT mohou obsahovat volitelné parametry jako kid (Key ID) a
jku (JWK Set URL), které serveru pomáhají určit, který podpisový klíč se má při
ověřování použít. Protože tyto hodnoty dodává klient, může jejich důvěřování bez řádné
validace vést k závažným zranitelnostem.
Mezi obvyklé vektory útoku patří:
- manipulace s parametrem
jkutak, aby odkazoval na JWKS endpoint ovládaný útočníkem; - zneužití průchodu adresáři (directory traversal) přes parametr
kid, pokud se klíče načítají přímo ze souborového systému; - zneužití SQL injection tam, kde se hodnota
kidvkládá do databázových dotazů.
Vyspělé knihovny pro práci s JWT tyto scénáře ošetřují bezpečně, vlastní ověřovací logika ale při bezpečnostních testech nadále generuje nálezy.
D. Selhání validace claimů
Platný podpis automaticky neznamená, že by se tokenu mělo věřit. Aplikace musí navíc ověřit každý claim, který má vliv na bezpečnost.
Při pentestech pravidelně narážíme na API, která:
- přijímají prošlé tokeny, protože ignorují claim
exp; - neověřují zamýšleného příjemce (
aud), takže lze tokeny přehrávat napříč různými službami; - důvěřují libovolné hodnotě vydavatele (
iss); - spoléhají výhradně na claimy pod kontrolou klienta, jako jsou
role,tenantnebopermissions, aniž by autorizaci vynucovaly na straně serveru.
Tyto logické chyby mívají v praxi větší dopad než kryptografické slabiny, protože umožňují použít legitimní tokeny způsobem, který nebyl zamýšlen.
Moderní nástroje pro testování bezpečnosti JWT
Ruční dekódování Base64 a manipulace s podpisy jsou neefektivní. Pentesteři se proto spoléhají na specializované nástroje, které tyto útoky automatizují:
- JWTAuditor:
vynikající platforma pro bezpečnostní testování běžící na straně klienta, ušitá na míru
pentesterům. Umožňuje rychlou inspekci, automatizovanou detekci zranitelností (například
testování algoritmu
nonenebo injektáže v hlavičce) a offline brute-force útoky bez rizika, že by se citlivé tokeny klienta dostaly do telemetrie třetích stran. - Burp Suite (rozšíření JWT Editor): hojně využívaný při dynamickém testování webu k manipulaci s tokeny za běhu během zachytávání provozu na HTTP proxy.
- JWT.io: spravovaný společností Auth0; jde o standardní nástroj pro rychlé ruční dekódování a pro ověření struktury a podpisu tokenu během úvodního průzkumu.
- JWTLens: odlehčená alternativa pro inspekci tokenů s důrazem na soukromí. Tokeny dekóduje a ověřuje kompletně v prohlížeči pomocí nativního Web Crypto API, takže vaše tokeny ani klíče nikdy neopustí váš počítač. Protože při ověřování neprobíhají žádné síťové požadavky, jde o ideální nástroj pro bezpečné ověřování algoritmů a podpisů.
Praktické obranné postupy
Aby se vaše aplikace nedostala mezi kritické nálezy v pentestové zprávě, měly by vývojové týmy vynucovat tyto základní kontroly:
- Mějte očekávané algoritmy napevno v kódu: nikdy nenechte příchozí token
určovat, jak se má ověřit. Explicitně nastavte validační rutinu tak, aby očekávala
konkrétní algoritmus (například
RS256), a algoritmusnonebezpodmínečně odmítejte. - Vynucujte úplnou validaci claimů: platný podpis dokazuje pouze to, že s
tokenem nikdo nemanipuloval; neznamená, že je token pro daného uživatele aktuálně platný.
Při každém jednotlivém požadavku explicitně ověřujte
exp(expiraci),iss(vydavatele) aaud(příjemce). - K symetrickým klíčům se chovejte jako k heslům: pokud vaše architektura
vyžaduje symetrické podepisování (
HS256), je váš tajný klíč fakticky rootovské heslo. Zajistěte, aby měl entropii alespoň 256 bitů, aby byl vygenerovaný kryptograficky bezpečným generátorem náhodných čísel a aby byl bezpečně uložený v proměnných prostředí nebo ve správci tajemství (secrets manager) – nikdy ne napevno ve zdrojovém kódu. - Pamatujte: kódování není šifrování. Do payloadu JWT nikdy neukládejte citlivá data, osobní údaje ani hesla. Kdokoli token zachytí, dokáže ho okamžitě dekódovat z Base64.
- Oddělte ukládání tokenů: krátkodobé access tokeny nikdy neukládejte do
localStorageanisessionStorage, odkud je dokáže odcizit jediná XSS zranitelnost. Access tokeny držte striktně v paměti na straně klienta a dlouhodobé refresh tokeny umístěte do zabezpečených cookies s příznakyHttpOnlyaSameSite.
Pokročilé zpevnění: vzor phantom token
V prostředích s vysokými nároky na bezpečnost je nejúčinnější obranou proti krádeži na straně klienta vůbec JWT frontendu nevystavovat. Moderní podnikové architektury proto často implementují vzor „phantom token“, a to v těchto krocích:
- Autorizační server vydá klientské aplikaci náhodný, neprůhledný (opaque) řetězec relace místo JWT.
- Když klient odešle požadavek na API, pošle právě tento neprůhledný řetězec.
- API gateway požadavek zachytí, ověří neprůhledný token proti autorizačnímu serveru (nebo úložišti relací) a vymění ho za plnohodnotný podepsaný JWT.
- API gateway předá skutečný JWT interním mikroslužbám.
Často kladené otázky o bezpečnosti JWT
01
Je JWT šifrovaný?
Ne. Hlavička a payload standardního podepsaného JWT (tedy JWS) jsou pouze zakódované pomocí Base64Url, nikoli zašifrované. Kdokoli, kdo token drží, si dokáže dekódovat a přečíst každý claim uvnitř. Podpis chrání integritu, nikoli důvěrnost, a proto do payloadu JWT nepatří žádná citlivá data ani osobní údaje.
02
Co je záměna algoritmů u JWT?
K záměně algoritmů dochází, když server nechá o způsobu ověření podpisu rozhodnout hlavičku
alg samotného tokenu. Útočník vezme veřejný RSA klíč serveru, změní hlavičku z
RS256 na HS256, upraví payload a celý token znovu podepíše, přičemž jako tajný klíč HMAC
použije právě tento veřejný klíč. Server, který akceptuje oba algoritmy, podvrh úspěšně
ověří. Řešením je mít očekávaný algoritmus napevno nastavený na straně serveru.
03
Kde se mají v prohlížeči ukládat access tokeny a refresh tokeny?
Krátkodobé access tokeny držte výhradně v paměti aplikace. Dlouhodobé refresh tokeny
ukládejte do cookies s příznaky HttpOnly, Secure a
SameSite, aby je nedokázal přečíst JavaScript. Ani jeden z tokenů nikdy
neukládejte do localStorage nebo sessionStorage, odkud je dokáže
odcizit jediná XSS zranitelnost.
04
Jak útočníci prolamují podpisové klíče HS256?
Zachycený token HS256 lze napadnout zcela offline nástroji jako Hashcat nebo John the Ripper, bez jakékoli další interakce s cílovou aplikací. Slabé klíče typu názvů firem, slovníkových slov nebo předvídatelných frází padnou často během několika minut a útočník pak dokáže vytvářet platné tokeny pro libovolného uživatele. Symetrické klíče potřebují alespoň 256 bitů entropie z kryptograficky bezpečného generátoru.
05
Znamená platný podpis, že se dá JWT věřit?
Ne. Platný podpis dokazuje pouze to, že s tokenem nikdo nemanipuloval. Aplikace musí navíc
ověřit každý claim relevantní pro bezpečnost: exp kvůli expiraci,
iss kvůli vydavateli a aud kvůli zamýšlenému příjemci – a nikdy
nesmí spoléhat na claimy dodané klientem, jako jsou role nebo
permissions, aniž by autorizaci vynucovala na straně serveru.
Jak může pomoci Haxoris
Bezpečnost tokenů se málokdy láme na kryptografii – láme se na konfiguraci. Haxoris vám pomůže tyto mezery najít dřív než útočník:
- Penetrační testování webových aplikací a API se zaměřením na autentizační a autorizační toky.
- Revize logiky vydávání a ověřování JWT a správy klíčů, včetně práce s JWKS a rotace klíčů.
- Offline posouzení síly symetrických podpisových klíčů.
- Revize návrhu ukládání tokenů, délky relací a architektury refresh tokenů.
Závěr
JWT nejsou nebezpečné ze své podstaty. Nebezpečnými se stávají ve chvíli, kdy aplikace nechá token rozhodovat o tom, jak se má ověřit, nebo když platný podpis považuje za náhradu autorizace. Mějte algoritmus napevno v kódu, ověřujte každý claim, chovejte se k tajným klíčům jako k rootovským heslům a nenechávejte tokeny v úložišti prohlížeče – a většina nálezů z tohoto článku z vaší příští pentestové zprávy zmizí.
Zdroje a doporučená četba
Metodiky a technické detaily v tomto článku vycházejí z následujících autoritativních bezpečnostních zdrojů:
- PortSwigger Web Security Academy. JWT Security Vulnerabilities. Podrobný rozbor chyb v ověřování podpisu a injektáží v hlavičce. portswigger.net/web-security/jwt
- InfoSec Writeups. JWT Pentesting: A Journey from Token to Takeover. Praktické případové studie zneužití konfigurace tokenů. infosecwriteups.com
- Auth0 / JWT.io. Introduction to JSON Web Tokens. Základní standardizační dokumentace ke struktuře tokenů a k RFC 7519. jwt.io/introduction
- JWTAuditor. Security Testing Tool. Použitý pro manipulaci s payloadem a automatizované posouzení zranitelností. jwtauditor.com