JWT-biztonság: sérülékenységek, támadások és védekezés

·

A JSON Web Token (JWT) mára az állapotmentes hitelesítés alapértelmezett eszköze a webalkalmazásokban. Rugalmas, és éppen ezért könnyű végzetesen elrontani a beállításait. Amikor egy vizsgálat során JWT-t látunk, nem a munkamenet azonosítóját látjuk benne, hanem kriptográfiai támadási felületet.

A lényeg röviden

  • A JWT kódolt, nem titkosított – a payloadban lévő claimeket (állításokat) elolvassa bárki, akinek a token a kezébe kerül.
  • Az algorithm confusion (RS256 helyett HS256) és a none algoritmus máig a legsúlyosabb hibák, amelyeket saját fejlesztésű és régi implementációkban találunk.
  • A HS256 titka jelszó. Egy elkapott token offline törhető Hashcattel, az alkalmazás felé egyetlen további kérés nélkül.
  • A klienstől érkező fejlécparaméterek – a kid és a jku – az aláírás ellenőrzését injekciós felületté változtatják.
  • Az érvényes aláírás semmit nem mond a claimek érvényességéről: az exp, az iss és az aud értékét minden kérésnél ellenőrizni kell.
  • Az access token a memóriában marad, a refresh token HttpOnly, Secure, SameSite cookie-ban – a localStorage egyikhez sem jó.

A JWT felépítése: fejléc, payload, aláírás

A JWT három részből áll: fejlécből, payloadból és aláírásból, ezeket pont (.) választja el egymástól. Proxyban elkapva egyetlen hosszú, véletlenszerűnek tűnő karakterláncnak látszik. Egy valódi példa:

eyJraWQiOiI5MTM2ZGRiMy1jYjBhLTRhMTktYTA3ZS1lYWRmNWE0NGM4YjUiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTY0ODAzNzE2NCwibmFtZSI6IkNhcmxvcyBNb250b3lhIiwic3ViIjoiY2FybG9zIiwicm9sZSI6ImJsb2dfYXV0aG9yIiwiZW1haWwiOiJjYXJsb3NAY2FybG9zLW1vbnRveWEubmV0IiwiaWF0IjoxNTE2MjM5MDIyfQ.SYZBPIBg2CRjXAJ8vCER0LA_ENjII1JakvNQoP-Hw6GG1zfl4JyngsZReIfqRvIAEi5L4HV0q7_9qGhQZvy9ZdxEJbwTxRs_6Lb-fZTDpW6lKYNdMyjw45_alSCZ1fypsMWz_2mTpQzil0lOtps5Ei_z7mM7M8gCwe_AGpI53JxduQOaB5HkT5gVrv9cKu9CsW5MS6ZbqYXpGyOG5ehoxqm8DL5tFYaW3lB50ELxi0KsuTKEbD0t5BCl0aCR2MBJWAbN-xeLwEenaqBiwPVvKixYleeDQiBEIylFdNNIMviKRgXiYuAvMziVPbwSgkZVHeEdF5MQP1Oe2Spac-6IfA

A fejléc és a payload egyszerű, Base64Url-kódolású JSON-objektum. Kódolt, nem titkosított: kulcs nélkül elolvassa bárki, aki hozzájut a tokenhez.

A JWT három része

A JWT – pontosabban JWS, vagyis a JWT aláírt változata – három, ponttal elválasztott szakaszból áll: Header.Payload.Signature.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhbmRyZWoiLCJyb2xlIjoiaGFja2VyIn0.MmM0ZGMxM2Y1NWQ2YTY2YTE
Fejléc · algoritmus és tokentípus
{ "alg": "HS256", "typ": "JWT" }
Payload · adatok
{ "sub": "andrej", "role": "hacker" }
Aláírás
HMACSHA256(
    base64UrlEncode(header) + "." +
    base64UrlEncode(payload),
    "secret"
) = MmM0ZGMxM2Y1NWQ2YTY2YTE

A fejléc

A fejléc magáról a tokenről árul el adatokat: a típusát és azt a kriptográfiai algoritmust, amellyel aláírták. A fenti token első szakasza ezt adja vissza:

{
    "kid": "9136ddb3-cb0a-4a19-a07e-eadf5a44c8b5",
    "alg": "RS256"
}

A payload

A payload hordozza a felhasználóra vonatkozó claimeket, és egy vizsgálat során ez az első számú célpont. A példa középső szakasza így néz ki:

{
    "iss": "portswigger",
    "exp": 1648037164,
    "name": "Andrej Šebeň",
    "sub": "andrej",
    "role": "pentester",
    "email": "andrej@haxoris.com",
    "iat": 1516239022
}

Az aláírás

A fejlécet és a payloadot bárki elolvashatja és át is írhatja, ezért a JWT-re épülő hitelesítés egésze a kriptográfiai aláíráson múlik.

A tokent kiállító szerver a Base64Url-kódolású fejlécből és payloadból titkos kulccsal képez lenyomatot. Ez két dolgot garantál:

  1. Az aláírás közvetlenül a token többi részéből származik: ha a fejlécben vagy a payloadban akár egy bájt megváltozik, az aláírás már nem illik hozzá.
  2. A szerver titkos kulcsa nélkül nem lehet érvényes aláírást előállítani hamisított fejléchez vagy payloadhoz.

Mit keres a támadó egy JWT-ben?

A JWT tervezésénél fogva olvasható, ezért a támadó felderítési anyagként kezeli, nem titkosított csomagként. A logikai hibák jellemzően a payloadban ülnek. Ezeket a claimeket nézzük meg elsőként:

ClaimSzerepEllenőrzési szempont
iss (Issuer)Megmondja, ki állította ki a tokent.Ellenőrzi ezt egyáltalán a backend? Az a rendszer, amelyik illetéktelen kiállítótól is elfogad tokent, kiszolgáltatott a token confusion nevű támadásnak.
sub (Subject)A felhasználó vagy entitás, amelyet a token képvisel – jellemzően egy azonosító.Insecure Direct Object Reference (IDOR). Átírható-e admin értékre vagy user_id=1 alakra, és megkerülhető-e vele a jogosultságellenőrzés?
aud (Audience)Az a fél, akinek a tokent szánták.Működik-e az egyik mikroszolgáltatásra kiállított token egy másik, sokkal nagyobb jogosultságú mikroszolgáltatásnál?
exp (Expiration Time)Az a Unix-időbélyeg, amikor a token lejár.Kikényszeríti ezt a szerver? Rendszeresen találunk olyan API-t, amelyik korlátlan ideig elfogadja a lejárt tokent.
nbf (Not Before)Az az időpont, amely előtt a tokent nem szabad elfogadni.Az ellenőrző logikából gyakran teljesen kimarad.
iat (Issued At)A token kiállításának ideje.Ebből számoljuk ki a tokenek élettartamát, és ez mutatja meg azokat is, amelyeket soha nem cserélnek le.

Felderítés a payloadból: amit egy token elárul

A payloadot bárki elolvassa, akinél a token megfordul, tehát a fejlesztőnek nyilvános adatként kell kezelnie. Vizsgálatok során rendszeresen találunk egyedi claimekben olyan belső részletet, aminek ott semmi keresnivalója:

  • A belső hálózat térképe: az olyan claimek, mint a "node_ip": "10.0.4.12", a "cluster": "prod-us-east-1a" vagy a "db_host": "internal-db.local", elárulják a belső architektúrát és a használt címtartományokat.
  • A keretrendszer és az identitásszolgáltató: a claimek elnevezése megmutatja a technológiai hátteret. A http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name egyértelműen Microsoft .NET / Entra ID rendszert jelez, így rögtön az arra jellemző sérülékenységeket keressük.
  • Személyes adatok: feleslegesen kiadott e-mail-cím, telefonszám, teljes név vagy lakcím – ezek a tokenben azonnal adatvédelmi kockázatot jelentenek (GDPR, CCPA).
  • Tenantok és szerepkörök felderítése: a "tenant_id": "uuid", az "is_god_mode": false vagy a "permissions": ["read:profile"] kirajzolja a jogosultsági modellt, és készen adja a paraméterneveket a jogosultságeszkalációhoz.

Egy valódi, túl bőbeszédű JWT-payload:

{
  "iss": "auth.internal-corp.local",
  "sub": "usr_99812",
  "email": "andrej@haxoris.com",
  "role": "admin",
  "internal_ip": "10.240.12.88",
  "db_shard": "shard-04-eu",
  "is_admin": true,
  "exp": 1748037164
}

Access token és refresh token: architektúra és tárolás

A biztonságos JWT-használat két tokenre épül: a rövid életű access tokenre (bearer token) és a hosszú életű refresh tokenre. A rossz tárolási hely a leggyakoribb hiba, amelyet ezen a területen jelentünk.

Access token (bearer token)

  • Az access token az API-hívásokat engedélyezi, és szándékosan rövid életű: jellemzően 5–15 perc.
  • A helye kizárólag az alkalmazás memóriája. A localStorage és a sessionStorage kiesik: egyetlen sikeres XSS elég ahhoz, hogy a token a támadóhoz kerüljön.

Refresh token

  • A refresh token egyetlen feladata, hogy a lejárt access token helyett újat lehessen kérni.
  • A helye HttpOnly, Secure, SameSite cookie: a JavaScript nem olvassa ki, az XSS-sel elkövetett tokenlopás sokkal nehezebb lesz, és a CSRF kockázata is csökken.

Gyakori JWT-támadások egy vizsgálat során

Egy webalkalmazás vizsgálatakor jellemzően végigmegyünk a következő támadási irányokon.

A. Hibák az aláírás ellenőrzésében

A JWT-sérülékenységek nagy része nem a kriptográfia gyengeségéből ered, hanem abból, hogy a szerver rosszul ellenőrzi az aláírást. Néhány könyvtár korábban elfogadta a none algoritmust: ilyenkor az aláírás egyszerűen elhagyható, a claimek – például a felhasználó szerepköre – pedig szabadon átírhatók. A ma használt könyvtárak alapértelmezés szerint elutasítják a none algoritmust, a hiba mégis előjön régi alkalmazásokban és saját fejlesztésű JWT-kezelésben. Nem szokványos technológiai háttér esetén mindig érdemes megnézni.

A másik klasszikus az algorithm confusion. Ez a JWT egyik legsúlyosabb hibája, úgyhogy érdemes pontosan végigkövetni.

  • Az RS256 aszimmetrikus algoritmus. A szerver a privát kulcsával írja alá a tokent, és a hozzá tartozó publikus kulccsal ellenőrzi. A publikus kulcs sokszor bárki számára elérhető – például a /.well-known/jwks.json végponton.
  • A HS256 szimmetrikus algoritmus. A szerver ugyanazzal a megosztott titokkal ír alá és ellenőriz.

A támadás akkor működik, ha a szerver mindkét algoritmust elfogadja, és sehol nincs rögzítve, melyiket várja:

  1. A támadó megszerzi a szerver publikus kulcsát, jellemzően egyenesen a JWKS-végpontról.
  2. Átírja a payloadot, például a "role": "user" értéket "role": "admin" értékre.
  3. A fejlécben az "alg": "RS256" helyett "alg": "HS256" értéket állít be.
  4. A teljes módosított tokent (fejléc és payload) újra aláírja, méghozzá a publikus kulccsal mint HS256-titokkal.
  5. A szerver megkapja a tokent, látja az alg: HS256 értéket, és a publikus kulcsot HMAC-titokként használva ellenőrzi. Egyezik – a hamisított token átmegy.
Algorithm confusion támadás a JWT ellen: az alg fejléc átírása RS256-ról HS256-ra, majd a token újraaláírása a szerver publikus kulcsával mint HMAC-titokkal

A hiba gyökere nem a kriptográfia, hanem az, hogy a szerver vakon a klienstől kapott alg fejlécre bízza, hogyan ellenőrizze a tokent. Az alg átírása normális esetben érvénytelenítené az aláírást, hiszen az aláírás a fejlécre és a payloadra együtt készül. Csakhogy a támadó az egész módosított tokent újra aláírja, így a lecserélt algoritmushoz tartozó aláírás tökéletesen érvényes.

A mai könyvtárak nagyrészt bezárták ezt a rést, régi alkalmazásokban és saját JWT-implementációkban azonban továbbra is felbukkan.

B. Gyenge aláíró kulcsok

Ha az alkalmazás szimmetrikus algoritmussal (HS256) ír alá, pontosan annyira biztonságos, amennyire az aláíráshoz használt titok.

Egy vizsgálat során elkapott JWT teljesen offline támadható, Hashcattel vagy John the Ripperrel. A cégnév, a szótári szó és a kitalálható jelmondat általában percek alatt elesik, onnantól pedig a támadó bármelyik felhasználó nevében állít ki érvényes tokent – anélkül, hogy még egyszer hozzányúlna az alkalmazáshoz.

C. Injekció a fejlécparamétereken keresztül

A JWT fejléce opcionális paramétereket is tartalmazhat – ilyen a kid (Key ID) és a jku (JWK Set URL) –, amelyek megmondják a szervernek, melyik kulccsal ellenőrizzen. Az értékeket a kliens küldi, tehát ha a szerver ellenőrzés nélkül megbízik bennük, komoly rés nyílik.

Gyakori támadási irányok:

  • a jku paraméter átírása a támadó saját JWKS-végpontjára;
  • directory traversal a kid paraméteren keresztül, ha a szerver közvetlenül a fájlrendszerből tölti be a kulcsokat;
  • SQL-injekció ott, ahol a kid értékét összefűzéssel illesztik egy SQL-lekérdezésbe.

A kiforrott JWT-könyvtárak ezeket az eseteket biztonságosan kezelik, a saját ellenőrzési logikából viszont máig kerülnek megállapítások a jelentéseinkbe.

D. Ellenőrizetlen claimek

Az érvényes aláírás önmagában nem jelenti azt, hogy a tokenben meg lehet bízni. Az alkalmazásnak minden biztonsági szempontból fontos claimet ellenőriznie kell.

Vizsgálatok során rendszeresen találunk olyan API-t, amely:

  • figyelmen kívül hagyja az exp claimet, és elfogadja a lejárt tokent;
  • nem ellenőrzi a címzettet (aud), így ugyanaz a token egy másik szolgáltatásban is működik;
  • bármilyen kiállítót (iss) elfogad;
  • kizárólag a klienstől érkező claimekre – role, tenant, permissions – támaszkodik, és a szerveroldalon nem kényszeríti ki a jogosultságokat.

A gyakorlatban az ilyen logikai hibák sokszor többet érnek a támadónak, mint a kriptográfiai gyengeségek: teljesen szabályos tokent lehet velük olyasmire használni, amire senki nem számított.

Eszközök a JWT-k vizsgálatához

Base64-et dekódolni és aláírást hamisítani kézzel lassú. Az automatizáláshoz ezeket az eszközöket használjuk:

  • JWTAuditor: kliensoldali, kifejezetten pentesztereknek készült platform. Gyors tokenvizsgálat, automatikus ellenőrzések (none algoritmus, fejlécinjekció) és offline törés – anélkül, hogy az ügyfél érzékeny tokenjei idegen telemetriába kerülnének.
  • Burp Suite (JWT Editor bővítmény): a dinamikus tesztek alapja. A HTTP-forgalmat proxyban elfogva menet közben módosítjuk vele a tokent.
  • JWT.io: az Auth0 tartja karban. Gyors kézi dekódoláshoz, a token szerkezetének és aláírásának ellenőrzéséhez a felderítés elején.
  • JWTLens: könnyű, adatvédelem-központú alternatíva. A tokent teljes egészében a böngészőben dekódolja és ellenőrzi, a natív Web Crypto API-val, tehát a tokenek és a kulcsok nem hagyják el a gépet. Az ellenőrzés egyetlen hálózati kérést sem küld, így algoritmust és aláírást biztonságosan lehet vele megnézni.

Hogyan védhető meg egy JWT-alapú hitelesítés?

Ahhoz, hogy az alkalmazás ne a jelentés kritikus megállapításai között végezze, ezt az öt szabályt érdemes kikényszeríteni:

  • Rögzítse az elvárt algoritmust: a beérkező token soha ne dönthesse el, hogyan kell ellenőrizni. Állítson be egyetlen konkrét algoritmust (például RS256), a none algoritmust pedig feltétel nélkül utasítsa el.
  • Ellenőrizze mindegyik claimet: az érvényes aláírás csak annyit bizonyít, hogy a tartalomhoz senki nem nyúlt hozzá – azt nem, hogy a token most, ennél a felhasználónál érvényes. Minden egyes kérésnél nézze meg az exp, az iss és az aud értékét.
  • Kezelje root jelszóként a szimmetrikus titkot: ha az architektúra szimmetrikus aláírást kíván (HS256), a kulcsnak legalább 256 bit entrópiája legyen, kriptográfiailag biztonságos generátorból származzon, és környezeti változóba vagy titokkezelőbe kerüljön – soha ne a forráskódba.
  • A kódolás nem titkosítás: a payloadban nincs helye érzékeny adatnak, személyes adatnak vagy jelszónak. Aki elkapja a tokent, egy másodperc alatt visszafejti a Base64-kódolást.
  • Válassza szét a tárolást: a rövid életű access token nem kerülhet localStorage-ba vagy sessionStorage-ba, ahonnan egyetlen XSS kiviszi. Az access token a böngésző memóriájában marad, a hosszú életű refresh token pedig Secure, HttpOnly, SameSite cookie-ba való.

Haladó védelem: a phantom token minta

Magas biztonsági igényű környezetben a kliensoldali tokenlopás ellen az véd a leghatékonyabban, ha a JWT el sem jut a frontendig. A nagyvállalati architektúrák ezt gyakran a „phantom token” mintával oldják meg:

  1. Az authorizációs szerver JWT helyett véletlenszerű, önmagában semmit el nem áruló azonosítót ad a kliensnek.
  2. A kliens ezt az azonosítót küldi minden API-híváskor.
  3. Az API-átjáró elfogja a kérést, az azonosítót az authorizációs szervernél (vagy a munkamenettárban) ellenőrzi, és teljes értékű, aláírt JWT-re cseréli.
  4. Az átjáró a valódi JWT-t továbbítja a belső mikroszolgáltatásoknak.

Gyakori kérdések a JWT-biztonságról

01

Titkosított-e a JWT?

Nem. Az aláírt JWT (vagyis a JWS) fejléce és payloadja csak Base64Url-kódolású, nem titkosított. Aki hozzájut a tokenhez, minden benne lévő claimet elolvas. Az aláírás a sértetlenséget védi, nem a bizalmasságot, ezért érzékeny adatnak és személyes adatnak nincs helye a JWT payloadjában.

02

Mit jelent az algorithm confusion a JWT-nél?

Az algorithm confusion akkor lép fel, ha a szerver a token saját alg fejlécére bízza, hogyan ellenőrizze az aláírást. A támadó fogja a szerver publikus RSA-kulcsát, a fejlécben az RS256 helyére HS256-ot ír, módosítja a payloadot, majd a teljes tokent újra aláírja, a publikus kulcsot használva HMAC-titokként. Az a szerver, amelyik mindkét algoritmust elfogadja, érvényesnek látja a hamisítványt. A megoldás: a szerveren rögzíteni kell az elvárt algoritmust.

03

Hol tárolható az access token és a refresh token a böngészőben?

A rövid életű access token kizárólag az alkalmazás memóriájában marad. A hosszú életű refresh token HttpOnly, Secure, SameSite cookie-ba való, hogy a JavaScript ne olvashassa ki. Egyik sem kerülhet localStorage-ba vagy sessionStorage-ba: onnan egyetlen XSS-sérülékenység mindkettőt kiviszi.

04

Hogyan törik fel a támadók a HS256 aláíró kulcsát?

Az elkapott HS256 token teljesen offline támadható, például Hashcattel vagy John the Ripperrel, az alkalmazás felé egyetlen további kérés nélkül. A gyenge titok – cégnév, szótári szó, kitalálható jelmondat – gyakran percek alatt elesik, onnantól pedig a támadó bármelyik felhasználó nevében állít ki érvényes tokent. A szimmetrikus titoknak legalább 256 bit entrópiája legyen, kriptográfiailag biztonságos generátorból.

05

Elég-e az érvényes aláírás ahhoz, hogy megbízzunk egy JWT-ben?

Nem. Az érvényes aláírás csak annyit bizonyít, hogy a tokenhez senki nem nyúlt hozzá. Az alkalmazásnak ezen felül minden biztonsági szempontból fontos claimet ellenőriznie kell: az exp a lejáratot, az iss a kiállítót, az aud a címzettet jelöli. És soha nem támaszkodhat a klienstől érkező claimekre, például a role vagy a permissions értékére, a szerveroldali jogosultságellenőrzés helyett.

Miben segít a Haxoris?

A tokenek biztonságát ritkán a kriptográfia töri meg – szinte mindig a konfiguráció. Ezeket a réseket még a támadó előtt megtaláljuk:

  • Webalkalmazásokat és API-kat tesztelünk, külön figyelemmel a hitelesítésre és a jogosultságkezelésre.
  • Átnézzük, hogyan állítja ki és ellenőrzi az alkalmazás a tokeneket, és hogyan kezeli a kulcsokat – a JWKS-t és a kulcscserét is beleértve.
  • Offline megnézzük, mennyire erős a szimmetrikus aláíró kulcs.
  • Átvilágítjuk a tervet: hol tárolja a tokent, meddig él a munkamenet, hogyan épül fel a refresh token körüli logika.

Összegzés

A JWT nem eleve rossz megoldás. Attól lesz azzá, hogy az alkalmazás a tokenre bízza, hogyan kell ellenőrizni – vagy hogy az érvényes aláírást jogosultságnak veszi. Rögzített algoritmus, minden claim ellenőrzése, root jelszóként kezelt titok és a böngésző tárolóin kívül tartott token: ezzel a négy szabállyal a cikkben felsorolt megállapítások többsége eltűnik a következő vizsgálati jelentésből.

Források és ajánlott olvasmányok

A cikk módszertani és technikai részletei az alábbi forrásokra épülnek:

  1. PortSwigger Web Security Academy. JWT Security Vulnerabilities. Részletes leírás az aláírás-ellenőrzés hibáiról és a fejlécinjekciókról. portswigger.net/web-security/jwt
  2. InfoSec Writeups. JWT Pentesting: A Journey from Token to Takeover. Gyakorlati esetek a tokenek rossz beállításainak kihasználásáról. infosecwriteups.com
  3. Auth0 / JWT.io. Introduction to JSON Web Tokens. A szabvány alapdokumentációja: a tokenek felépítése és az RFC 7519. jwt.io/introduction
  4. JWTAuditor. Security Testing Tool. Eszköz a payload módosításához és az automatikus ellenőrzésekhez. jwtauditor.com
Pavol Litauszki

Szerző

Pavol Litauszki

Ne várjon a támadóra – nézzük meg, hol törik meg a hitelesítés az alkalmazásában!

Ingyenes konzultációt kérek