
CVE-2025-65945 के लिए प्रूफ ऑफ कॉन्सेप्ट (node-jws में क्रिप्टोग्राफिक हस्ताक्षर का अनुचित सत्यापन)
यह node-jws लाइब्रेरी में हस्ताक्षर सत्यापन बाईपास के लिए एक प्रूफ ऑफ कॉन्सेप्ट है। यह बग हमलावरों को वैध JWT बनाने की अनुमति देता है जब सर्वर उपयोगकर्ता-नियंत्रित डेटा से HMAC रहस्य प्राप्त करता है।
jws.createVerify() फ़ंक्शन यह मान्य नहीं करता कि HMAC एल्गोरिदम का उपयोग करते समय वास्तव में एक रहस्य प्रदान किया गया था। यदि आपका ऐप JWT में किसी चीज़ (जैसे kid हेडर) के आधार पर रहस्य खोजता है और वह खोज विफल होती है, तो आप एक खाली रहस्य के विरुद्ध सत्यापन कर सकते हैं।
एक हमलावर इसका शोषण इस प्रकार कर सकता है:
undefined लौटाता है, जो खाली स्ट्रिंग में बदल जाता हैहमलावर अब किसी का भी रूप धारण कर सकता है या स्वयं को व्यवस्थापक विशेषाधिकार प्रदान कर सकता है।
इसे ठीक करने के लिए 3.2.3+ या 4.0.1+ पर अपग्रेड करें।
सुनिश्चित करें कि आपके पास Bun स्थापित है, फिर:
# कमजोर संस्करण स्थापित करें
bun install [email protected]
# एक्सप्लॉइट चलाएं
bun run exploit.js
आपको आउटपुट दिखना चाहिए जो एक जाली व्यवस्थापक टोकन को वैध के रूप में स्वीकार किए जाने को दर्शाता है।
PoC एक सर्वर का अनुकरण करता है जो:
kid (कुंजी ID) हेडर के आधार पर रहस्य खोजता हैcreateVerify() का उपयोग करता हैहमलावर kid: "non-existent-key" के साथ एक JWT बनाता है और उसे एक खाली रहस्य के साथ हस्ताक्षरित करता है। जब सर्वर इस कुंजी को खोजने का प्रयास करता है, तो उसे undefined मिलता है, सत्यापन स्ट्रीम में एक खाली स्ट्रिंग लिखता है, और जाली टोकन सत्यापन पास कर लेता है।
# पैच किए गए संस्करण में अपग्रेड करें
bun install [email protected]
# फिर से चलाएं - अब विफल होना चाहिए
bun run exploit.js
पैच किए गए संस्करण के साथ, आपको एक त्रुटि दिखाई देगी: secret must be a string or buffer or a KeyObject। फिक्स यह सत्यापित करता है कि HMAC संचालन में आगे बढ़ने से पहले एक उचित रहस्य है।
यदि आपका कोड कुछ इस तरह दिखता है, तो आप प्रभावित हो सकते हैं:
const decoded = jws.decode(token);
const secret = lookupSecret(decoded.header.kid); // might return undefined!
const verifier = jws.createVerify({
algorithm: "HS256",
signature: token,
});
verifier.secret.write(secret); // oops
verifier.secret.end();