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 none zů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 kid a jku, mění ověřování podpisu v prostor pro injektáž.
  • Platný podpis neříká nic o platnosti claimůexp, iss a aud je 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, Secure a SameSite – nikdy ne v localStorage.

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.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhbmRyZWoiLCJyb2xlIjoiaGFja2VyIn0.MmM0ZGMxM2Y1NWQ2YTY2YTE
Hlavička · algoritmus a typ tokenu
{ "alg": "HS256", "typ": "JWT" }
Payload · data
{ "sub": "andrej", "role": "hacker" }
Podpis
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:

  1. 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.
  2. 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/name signalizují 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": false nebo "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 localStorage a sessionStorage, 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, Secure a SameSite, 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á:

  1. Útočník získá veřejný klíč serveru, často zcela triviálně z JWKS endpointu.
  2. Upraví payload tokenu – například povýší "role": "user" na "role": "admin".
  3. Změní hlavičku z "alg": "RS256" na "alg": "HS256".
  4. Znovu podepíše celý upravený token (hlavičku i payload), přičemž jako tajný klíč pro HS256 použije veřejný klíč.
  5. Server token přijme, uvidí alg: HS256 a ověří ho pomocí veřejného klíče jako HMAC klíče. Podpis sedí a podvržený token je akceptován.
Útok záměnou algoritmů u JWT: změna hlavičky alg z RS256 na HS256 a opětovné podepsání tokenu veřejným klíčem serveru použitým jako tajný klíč HMAC

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 jku tak, 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 kid vklá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, tenant nebo permissions, 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 none nebo 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 algoritmus none bezpodmí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) a aud (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 localStorage ani sessionStorage, 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říznaky HttpOnly a SameSite.

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:

  1. Autorizační server vydá klientské aplikaci náhodný, neprůhledný (opaque) řetězec relace místo JWT.
  2. Když klient odešle požadavek na API, pošle právě tento neprůhledný řetězec.
  3. 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.
  4. 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ů:

  1. 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
  2. InfoSec Writeups. JWT Pentesting: A Journey from Token to Takeover. Praktické případové studie zneužití konfigurace tokenů. infosecwriteups.com
  3. Auth0 / JWT.io. Introduction to JSON Web Tokens. Základní standardizační dokumentace ke struktuře tokenů a k RFC 7519. jwt.io/introduction
  4. JWTAuditor. Security Testing Tool. Použitý pro manipulaci s payloadem a automatizované posouzení zranitelností. jwtauditor.com
Pavol Litauszki

Autor

Pavol Litauszki

Nečekejte na útočníky – odhalte své nejslabší místo penetračním testem už teď!

Rezervovat