Intervjuer iz Huolala: Šta ako se JWT "uhvati"?
Jedan član kluba na planetu pitao je: na intervjuu sam naišao na pitanje, ako neko uhvati jwt prateći pakete, kako da reagujem?
Prvobitno sam hteo lično da napišem članak, ali sam slučajno video ovaj post na javnom nalogu Huolala tehnologije, neočekivano detaljno napisan, pa sam ga direktno uključio, jednostavno prilagodio neke detalje, možete dobro pogledati, pravi sadržaj.

1. JWT uvod
JSON Web Token (JWT) je kompaktan, JSON-baziran otvoreni standard (RFC 7519), često korišćen za siguran prenos informacija između različitih subjekata (klijenta i servera). JWT se obično sastoji od tri dela:
- Header (zagavlje): definiše tip tokena i algoritam enkripcije, npr.
{"alg": "HS256", "typ": "JWT"} - Payload (teret): sadrži informacije o tvrdnjama (claims), npr. identitet korisnika, dozvole itd.
- Signature (potpis): koristi se za verifikaciju autentičnosti i integriteta tokena.
Primer JWT-a:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cJWT se široko koristi za autentifikaciju identiteta, scenarije autorizacije. Kada server verifikuje JWT, može proceniti da li je poruka promenjena dešifrovanjem potpisa.
2. JWT površine sopstvenih napada
2.1 Napad zabune algoritma (Algorithm Confusion Attack)/Napad "None" algoritma
Tehničke tačke:
- Napadač može falsifikovati legalni Token menjajući Header deo JWT-a, menjajući algoritam potpisivanja sa sigurnog (npr. HS256) na nesiguran (npr. none).
- Napadač može iskoristiti slabosti mehanizma verifikacije servera menjajući polje algoritma u JWT-u (npr. iz RSA u HMAC), korišćenjem javnog ključa za ponovno potpisivanje tokena i slanjem nazad, dovodeći do uspešne verifikacije, iako je token već falsifikovan.
Primer:
Originalni Header:
{"alg": "HS256","typ": "JWT"}Posle napada promenjen u:
{"alg": "none","typ": "JWT"}U ovom trenutku JWT neće vršiti verifikaciju potpisa, napadač može falsifikovati proizvoljan Payload. Na primer:
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJ1c2VySWQiOiIxMjMifQ.Rešenja:
- Na strani servera strogo verifikujte polje alg, ne dozvolite korišćenje nesigurnih algoritama kao što je none.
- Prilikom generisanja i parsiranja JWT-a, eksplicitno navedite i verifikujte sigurne algoritme, npr. HS256 ili HS512.
payload = jwt.decode(token, self.secret, algorithms=["HS256", "HS512"])
userId = payload['userId']
username = self.db_lookup(userId, "username")2.2 Slabi ključevi dovode do toga da Token može biti falsifikovan
Tehničke tačke:
- Ako server koristi slabe ključeve ili nepravilno upravlja ključevima, napadač može falsifikovati JWT putem brutalnog razbijanja ili otkrivenih ključeva, zaobilazeći verifikaciju.
- U simetričnoj enkripciji (npr. HMAC), jačina potpisa JWT-a zavisi od kompleksnosti ključa. Ako se koristi slab ključ, napadač može otkriti ključ brutalnim razbijanjem i generisati falsifikovani JWT.
Primer: Ako je ključ suviše jednostavan, napadač može koristiti alate kao jwtcrack da razbi potpis:
jwtcrack your_jwt_tokenPosle razbijanja, napadač može koristiti ovaj ključ da generiše falsifikovani JWT.
Rešenja:
- Koristite jake algoritme enkripcije, npr. RS256 (asimetrična enkripcija), izbegavajte simetrične algoritme enkripcije kao HS256.
payload = jwt.decode(token, self.secret, algorithms="RS256")- Koristite ključeve visokog intenziteta i čuvajte ih na sigurnom, izbegavajte curenje.
2.3 Napad ponovnog reproduciranja tokena (Token Replay Attack)
Tehničke tačke:
- Napadač može presresti JWT legalnog korisnika i ponoviti ga tokom njegovog važenja, vršeći napad ponovnog reproduciranja.
- Pre verifikacije potpisa Tokena, biće izračunato važenje Tokena, da bi se osiguralo da Token još uvek nije istekao. Obično se ovo radi čitanjem exp (vreme isteka) tvrdnje iz Tokena i računanjem da li je još uvek važeće. Ako je vrednost exp prevelika (ili uopšte nije postavljena), važenje Tokena biće predugo, čak se možda nikada neće istekati.
Primer: Pretpostavimo da napadač je uhvatio legalni JWT i konstantno reproducira taj zahtev da izvrši neovlašćenu radnju tokom njegovog važenja.
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Rešenja:
- Postavite kraće vreme isteka exp da ograničite važenje Tokena.
lifetime = datetime.datetime.now + datetime.timedelta(minutes=5)
payload = {
'username' : username,
'admin' : 0,
'exp' : lifetime
}
access_token = jwt.encode(payload, self.secret, algorithm="HS256")- Koristite jedinstveni identifikator (npr. nonce) u procesu generisanja Tokena da sprečite napad ponovnog reproduciranja.
- Na strani servera održavajte istoriju korišćenja Tokena, odbijte ista Token da bude korišćen više puta.
2.4 Rizik curenja i krađe Tokena
Tehničke tačke:
Ako se JWT prenosi kroz nesigurne kanale prenosa, npr. korišćenjem HTTP umesto HTTPS, napadač može presresti i dobiti JWT putem napada "čovek u sredini".
Rešenja:
- Uvek koristite HTTPS za prenos JWT-a, izbegavajte napad "čovek u sredini".
- Izbegavajte prenos JWT-a u URL-u, jer URL može biti zabeležen u logovima.
2.5 JWT Header parametar injekcija falsifikuje samopotpis
Parametri Header-a definisani u JSON Web Signature (JWS) RFC, osnovni JWT header je sledeći JSON.
{
"typ": "JWT",
"alg": "HS256"
}Ostali parametri Header-a registrirani u RFC-u uključuju: jwk, jku, kid itd:
jwk(JSON Web Key): obezbeđuje ugrađeni JSON objekat koji predstavlja ključjku(JSON Web Key Set URL): obezbeđuje URL, server sa ovog URL može dobiti skup ključeva koji sadrži ispravan ključkid(Key ID): obezbeđuje ID, server ga može koristiti da identifikuje ispravan ključ kada je više ključeva na izboru, u zavisnosti od formata ključa ovo može imati odgovarajući kid parametar
Svi ovi korisnički kontrolisani parametri Header-a kažu serveru koji ključ treba koristiti pri verifikaciji potpisa, ako konfiguracija servera ima nedostataka, kroz injekciju ovih parametara može se falsifikovati legalni samopotpisani JWT.
Kroz jwk parametar injekcija samopotpisani JWT:
Primer:
{
"kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG",
"typ": "JWT",
"alg": "RS256",
"jwk": {
"kty": "RSA",
"e": "AQAB",
"kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG",
"n": "yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9m"
}
}Tehničke tačke:
U idealnom slučaju, server bi trebalo da koristi samo ograničenu belu listu javnih ključeva za verifikaciju JWT potpisa. Međutim, pogrešno konfigurisani server ponekad koristi bilo koji ključ ugrađen u jwk parametru. Korišćenjem sopstvenog RSA privatnog ključa za potpisivanje izmenjenog JWT-a, zatim ugradnjom odgovarajućeg javnog ključa u jwk, server će koristiti javni ključ ugrađen u jwk za verifikaciju JWT potpisa, dovodeći do toga da falsifikovani samopotpisani JWT prođe verifikaciju.
Rešenja:
Ispravna konfiguracija bele liste javnih ključeva na serveru za verifikaciju JWT potpisa
Kroz jku parametar injekcija samopotpisani JWT
Primer:
{"typ":"JWT","alg":"RS256", "jku":"https://hacker.com/jwks.json", "kid":"id_of_jwks"}.
{"login":"admin"}.
[Signed with new Private key; Public key exported]Tehničke tačke:
Različito od jwk, jku parametar je URL ka fajlu skupa jwk. Napadač zamenjuje jku URL URL-om koji sadrži zlonameran javni ključ, zatim koristi parni privatni ključ da potpiše falsifikovani Token, server dobavlja zlonameran javni ključ i verifikuje falsifikovani Token kao legalan.
Rešenja:
Server koristi belu listu da verifikuje vrednost jku parametra, dozvoljava samo URLove navedenog izvora
Kroz kid parametar injekcija samopotpisani JWT
Primer:
{
"kid": "../../path/to/file",
"typ": "JWT",
"alg": "HS256",
"k": "asGsADas3421-dfh9DGN-AFDFDbasfd8-anfjkvc"
}Tehničke tačke:
Server može koristiti više ključeva za potpisivanje različitih vrsta podataka, stoga Header parametri JWT-a mogu sadržati kid(Key ID) parametar, da server pri verifikaciji potpisa odredi koji ključ koristiti, ključevi za verifikaciju se obično čuvaju kao skup JWK, u ovom slučaju server može jednostavno tražiti JWK koji ima isti kid kao Token, međutim JWS specifikacija ne definiše konkretnu strukturu za kid — to je proizvoljan niz koji biraju programeri, na primer: mogu koristiti kid parametar da pokazuju na specifični unos u bazi podataka, čak i naziv fajla, ako ovaj parametar takođe ima ranjivost prelaska direktorijuma, napadač može primorati server da koristi proizvoljan fajl u fajl sistemu kao verifikacioni ključ, na primer ../../../../../../../dev/null, jer je ovo prazan fajl, čitanje će vratiti prazan niz. Stoga, korišćenje praznog niza za potpisivanje Tokena će dobiti legalni potpis koji prolazi verifikaciju servera.
Rešenja:
Server koristi belu listu da verifikuje vrednost kid parametra.
3. JWT površine napada u poslovnim scenarijima
3.1 Curenje osetljivih informacija
Tehničke tačke:
Payload JWT-a je Base64 kodiran, a ne enkriptovan, stoga se sadržaj može lako parsirati. Ako Payload sadrži osetljive informacije (npr. identitet korisnika, email itd.), može doći do curenja informacija.
Primer:
{"SSN": "123-45-6789","email": "user@example.com","role": "admin"}Napadač može lako dekodirati Base64 deo i dobiti ove osetljive podatke.
Rešenja:
- Izbegavajte čuvanje osetljivih informacija u JWT Payload-u, koristite identifikatore (npr. userId), umesto podataka u plain textu.
payload = jwt.decode(token, self.secret, algorithms="HS256")
userId = payload['userId']
password = self.db_lookup(userId, "password")- Ako morate sadržati osetljive informacije, treba koristiti mehanizam enkripcije za enkripciju Payload-a.
3.2 Greška u logici autentifikacije dovodi do mešanja JWT-a
Tehničke tačke:
U određenim scenarijima, ako različiti tipovi identiteta JWT-a (npr. Tokeni administratora i običnog korisnika) nisu strogo razdvojeni, može doći do problemima kao što je povećanje dozvola.
Primer: Određeni servis dozvoljava korisnicima da koriste JWT običnog korisnika za pristup administrativnom interfejsu, napadač može iskoristiti ovu ranjivost da poveća dozvole:
POST /admin/manage/add HTTP/2
Authorization: Bearer user_token_with_low_permissionsRešenja:
- Dodajte verifikaciju tipa Tokena i dozvola u poslovnoj logici, osigurajte da se Tokeni različitih identiteta ne mogu mešati.
- Eksplicitno navedite ulogu korisnika u JWT Payload-u i verifikujte njegove dozvole na serveru.
- Ako su i administratorovi i obični korisnički JWT tipovi simetrične enkripcije, koristite različite ključe za potpisivanje i verifikaciju.
3.3 Napad releja između servisa
Tehničke tačke:
U scenariju više servisa, ako nije specificiran audience limit da Token može pristupati samo navedenoj aplikaciji, može doći do toga da Token aplikacije A može biti legalno korišćen u aplikaciji B, što može dovesti do povećanja dozvola.
Primer: Servis A dozvoljava korisnicima da koriste JWT generisan od strane servisa B za pristup, napadač može iskoristiti ovu ranjivost da proširi prava pristupa:
Host:appA
Authorization: Bearer user_token_made_by_appBRešenja:
- U scenariju više servisa, svaki servis pojedinačno verifikuje audience da spreči pristup Tokena drugih servisa
payload = jwt.decode(token, self.secret, audience=["appB"], algorithms="HS256")- Ako JWT svih servisa koriste algoritme simetrične enkripcije, svaki servis koristi različite ključeve za potpisivanje i verifikaciju
3.4 Redovni rizici injekcije i neovlašćenog pristupa
Tehničke tačke:
Napadači mogu pokušati da konstruišu zlonameran JWT kako bi zaobišli proveru dozvola ili ubacili zlonamerane podatke, vršeći neovlašćene radnje.
Primer: Napadač konstruiše sledeći Payload, pokušavajući da zaobiđe proveru dozvola:
{"userId": "123","role": "admin"}
{"userId": "123","username": "admin' or 1=1#","password": "null"}Ako server ne verifikuje legalnost Tokena, napadač može dobiti administratorske dozvole.
Rešenja:
- Strogo verifikujte potpis, algoritam i format JWT-a, osigurajte da Token nije promenjen.
- U svakom poslovnom interfejsu, pravilno tretirajte verifikaciju dozvola Tokena, izbegavajte neovlašćene radnje; filtrirajte podatke predstavljene u JWT-u, sprečite zlonamerane podatke da utiču na poslovne procese.
4. JWT testiranje
Kompletan proces testiranja JWT-a
https://github.com/ticarpi/jwt_tool/wiki/Attack-Methodology
Početak:
- Pronađite JWT
- Pronađite testni interfejs
- Reproduktujte zahtev da proverite da li je JWT važeći
Jednostavne provere:
- Da li je JWT obavezan?
- Da li JWT verifikuje potpis?
- Da li JWT može biti kontinuirano korišćen?
- Da li se JWT generiše na klijentu?
- Da li interfejs prvo verifikuje JWT pa obrađuje Payload?
- Da li JWT simetričnog algoritma enkripcije koristi slab ključ?
Testiranje poznatih ranjivosti:
- 'none' Algorithm (CVE-2015-9235)
- RSA Key Confusion (CVE-2016-5431)
- JWKS Injection (CVE-2018-0114)
- null signature (CVE-2020-28042)
Testiranje drugih ranjivosti:
- "kid" problemi - otkrij ključ i prelaz direktorijuma
- Napad falsifikovanja URL-a
- JWKS prevara
Dodatne provere:
- Napad releja između servisa/greška u logici autentifikacije istog servisa
- Da li JWT verifikuje važenje exp
Dalje:
- Redovne ranjivosti kao injekcija, neovlašćeni pristup itd.
- Fazi testiranje
5. Srodni alati
JWT.io
- https://jwt.io/
- Online alat, može parsirati i debugovati JWT, pomaže programerima da vide sadržaj i algoritam potpisa JWT-a, prepoznaju uobičajene probleme.
JWT Tool
- https://github.com/ticarpi/jwt_tool
- Alat za analizu, generisanje i napadanje JWT-a, podržava različite metode kao napad zabune algoritma itd.
jwtcrack
- https://github.com/Sjord/jwtcrack
- Rečno enumerisanje razbijanja JWT algoritama enkripcije HS256, HS384 ili HS512
CyberChef
- https://gchq.github.io/CyberChef/
- Online alat za verifikaciju, dekodiranje, potpisivanje JWT-a
JWS biblioteka
- Pruža biblioteke za generisanje i verifikaciju JWT-a, podržava više algoritama potpisivanja, može se koristiti za implementaciju logike sigurnog tretmana Tokena.
Burp Suite dodatak
- Burp Suite marketplace
- sign-saboteur: https://github.com/d0ge/sign-saboteur: za uređivanje, potpisivanje, verifikaciju različitih potpisanih Web Tokena
