
Keycloak डेटाबेस में CVE-2026-18963 एक्सप्लॉइटेशन के निशान खोजें (Keycloak बिना प्रमाणीकरण के खाता अपहरण)
एक psql स्क्रिप्ट जो Keycloak PostgreSQL डेटाबेस में CVE-2026-18963 के शोषण
(reset-credentials प्रवाह के माध्यम से बिना प्रमाणीकरण के खाता अधिग्रहण) के
निशान खोजती है।
KYOS द्वारा प्रकाशित। हमने इसे उन Keycloak परिनियोजनों को पैच करते समय लिखा था जिन्हें हम संचालित करते हैं, ताकि यह सत्यापित किया जा सके कि एक्सपोज़र विंडो के दौरान किसी का भी खाता अधिग्रहण नहीं हुआ था।
CVE-2026-18963, keycloak-services के reset-credentials प्रवाह में एक त्रुटि है
(keycloak#51833)। एक
अप्रमाणित हमलावर मेल सत्यापन लिंक पर क्लिक किए बिना किसी भी उपयोगकर्ता के लिए
पासवर्ड रीसेट प्रक्रिया पूरी कर सकता है, और फिर खाते पर नया पासवर्ड सेट कर सकता
है। किसी उपयोगकर्ता इंटरैक्शन की आवश्यकता नहीं है।
एक डिस्पोज़ेबल इंस्टेंस पर Keycloak 26.7.1 के विरुद्ध जाँच किया गया। हम पुनरुत्पादन चरण प्रकाशित नहीं कर रहे हैं; नीचे दिए गए विवरण वही हैं जिनकी आपको क्वेरीज़ को पढ़ने के लिए आवश्यकता है।
प्रवाह यह ट्रैक करता है कि वह किस प्रमाणक स्क्रीन पर है, ऐसे तरीके से जो उसे
सेट करने वाले चरण से जुड़ा नहीं है। इससे reset-credentials प्रवाह को मेल-सत्यापन
चरण पर पुनः प्रवेश कराया जा सकता है, जहाँ भेद्य ResetCredentialEmail.action()
किसी भी action token की जाँच किए बिना सफलता लौटाता है। इसके बाद निष्पादन
update-password फ़ॉर्म तक आगे बढ़ता है।
दो परिणाम इस रेपो की प्रत्येक क्वेरी को आकार देते हैं:
SEND_RESET_PASSWORD इवेंट लिखता है। उस इवेंट का अनुपस्थित होना कोई हस्ताक्षर
नहीं है।action() लौटने से पहले खाते के ईमेल पते को सत्यापित के रूप में
चिह्नित कर देता है। वैध पथ action() तक कभी पहुँचता ही नहीं, इसलिए यह एक
ऐसा स्थिति परिवर्तन है जो केवल बायपास उत्पन्न करता है। Q3 इसी पर आधारित है।फ़िक्स (keycloak#51844) स्क्रीन
स्थिति को उसे सेट करने वाले निष्पादन से जोड़ता है, और action() को केवल तभी
सफल होने देता है जब उस विशिष्ट उपयोगकर्ता के लिए एक action token मौजूद हो।
गंभीरता: Critical, CVSS v3.1 9.1 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N),
Red Hat और
NVD के अनुसार। मूल कारण
प्रमाणीकरण प्रवाह में अनुचित स्थिति सत्यापन है, जिसे
keycloak#51844 में ठीक किया
गया है।
| स्ट्रीम | इसमें ठीक किया गया |
|---|---|
| 26.7.x | 26.7.2 (रिलीज़ नोट्स) |
| 26.6.x | 26.6.6 |
| 26.4.x (LTS) | 26.4.15 |
| 26.8 | 26.8.0 |
समर्थित स्ट्रीम्स में इन संस्करणों से नीचे का सब कुछ भेद्य है। समर्थन से बाहर हो चुके रिलीज़ (26.5.x, 26.3 और उससे पुराने) को कोई फ़िक्स नहीं मिलता: एक्सपोज़र मान लें और किसी ठीक किए गए स्ट्रीम पर अपग्रेड करें। Red Hat, लेगेसी RH-SSO 7 को अप्रभावित के रूप में सूचीबद्ध करता है; Red Hat Build of Keycloak 26.4/26.6 को 26.4.15-1 / 26.6.6-1 में ठीक किया गया है।
स्व-सेवा पासवर्ड रीसेट अक्षम करने से भेद्य प्रवेश बिंदु हट जाता है:
Admin console > Realm settings > Login > प्रत्येक रियल्म के लिए "Forgot password"
बंद करें। एडमिन API के माध्यम से: PUT /admin/realms/{realm} के साथ
{"resetPasswordAllowed": false}।
यह login-actions/reset-credentials एंडपॉइंट को अवरुद्ध करता है, लेकिन वैध
उपयोगकर्ताओं को भी अपना पासवर्ड रीसेट करने से रोकता है, इसलिए इसे अपग्रेड करने
तक एक अस्थायी उपाय मानें। ध्यान दें कि Red Hat इस CVE के लिए कोई अनुमोदित
शमन उपाय सूचीबद्ध नहीं करता; पैचिंग ही एकमात्र वास्तविक समाधान है।
इस स्क्रिप्ट के पहले संस्करण ने एक पूर्ण हुए रीसेट को चिह्नित किया था जिसके
ठीक पहले कोई SEND_RESET_PASSWORD नहीं था।
यह गलत था, और
vilmosnagy ने इसे इंगित किया
अपने स्वयं के इंस्टेंस पर CVE को पुनः उत्पन्न करने और घटना को फिर भी प्रकट होते देखने के बाद। कारण ऊपर दिया गया पहला परिणाम है: मेल प्रमाणकर्ता सामान्य रूप से चलता है, इसलिए पीड़ित को एक वास्तविक रीसेट मेल मिलता है और Keycloak एक सामान्य SEND_RESET_PASSWORD लॉग करता है। जाँच उलटी थी। यह हर उस समझौता किए गए खाते को साफ़ कर देती जिसे वह देखती। इसे हटा दिया गया है।
टाइमिंग योजनाओं में एक छोटी लेकिन वास्तविक समस्या है। thomasdelorge की हंट स्क्रिप्ट में दृष्टिकोण एक साझा code_id पर SEND_RESET_PASSWORD को UPDATE_PASSWORD के साथ सहसंबंधित करता है और एक छोटे अंतराल को चिह्नित करता है। सहसंबंध कुंजी सही है, और लेखक स्पष्ट रूप से कहते हैं कि थ्रेशोल्ड एक अनुमानी (heuristic) है। हमारे परीक्षण भी यही कहते हैं: एक बायपास किया गया रीसेट और उसी ब्राउज़र में पूरा किया गया एक वैध रीसेट समान घटना प्रकार, समान विवरण कुंजियाँ और समान code_id उत्पन्न करते हैं। केवल विलंब भिन्न होता है, जिससे पूरा निर्णय थ्रेशोल्ड पर टिक जाता है। जिसे कोई जल्दी नहीं है वह उसके नीचे रह जाता है। वास्तविक उपयोगकर्ता इसे ट्रिगर कर देते हैं, क्योंकि code_id तभी समान रहता है जब लिंक उसी ब्राउज़र में खोला जाए जिसने प्रवाह शुरू किया था, और यह भी वही स्थिति है जहाँ मेल संभवतः पहले से खुला हुआ होता है।
हमें कोई घटना, कोई घटना विवरण और कोई त्रुटि नहीं मिली जो दोनों को अलग कर सके। देखने के लिए कोई "मेल चरण छोड़ा गया" घटना नहीं है। जो मौजूद है वह एक स्थिति का दुष्प्रभाव है, और यही Q3 उपयोग करता है।
cve-2026-18963-keycloak-hunt.sql छह केवल-पढ़ने वाली क्वेरी चलाती है:
| क्वेरी | यह क्या पाती है |
|---|---|
| Q0 | क्या realm घटनाओं को संग्रहीत करता है, उनका TTL, और क्या घटना विवरण संग्रहीत किए जा रहे हैं। Q2 code_id विवरण पर सहसंबंधित करता है, इसलिए यदि विवरण अनुपस्थित हैं तो Q2 अंधा है और उसकी चुप्पी का कोई अर्थ नहीं। |
| Q1 | एक्सपोज़र विंडो (credential.created_date) के भीतर सेट किया गया प्रत्येक पासवर्ड क्रेडेंशियल। यह स्वयं अधिग्रहण है, और यह घटना समाप्ति से बच जाता है। |
| Q2 | प्रत्येक पूर्ण किया गया क्रेडेंशियल अपडेट, जिसे उसी प्रमाणीकरण सत्र के रीसेट मेल के साथ सहसंबंधित किया गया है, और वर्गीकृत किया गया है। नीचे देखें। |
| Q3 | नियतात्मक दुष्प्रभाव: वे उपयोगकर्ता जो email_verified हैं और जिनका कोई वैध कारण नहीं है। |
| Q4 | Admin-API क्रेडेंशियल रीसेट और उपयोगकर्ता लेखन, ताकि Q1 और Q3 पंक्तियों को समझाया जा सके और admin-चालित मार्ग को बाहर रखा जा सके। |
| Q5 | कच्ची रीसेट/क्रेडेंशियल घटना टाइमलाइन, किसी एकल मामले को हाथ से पढ़ने के लिए। |
| निर्णय | अर्थ |
|---|---|
NO_MAIL_WAS_SENT | क्रेडेंशियल अपडेट एक विफल भेजने के साथ code_id साझा करता है: खाते पर कोई पता नहीं, या SMTP ने इसे अस्वीकार कर दिया। सर्वर से कोई लिंक कभी नहीं निकला, इसलिए कोई इसे खोल भी नहीं सकता था, फिर भी प्रवाह पासवर्ड फ़ॉर्म तक पहुँच गया। वैध रूप से असंभव; इसे शोषण मानें। |
CLEARED_TOKEN_CLICKED | रीसेट उस उपयोगकर्ता के किसी भी SEND_RESET_PASSWORD से भिन्न code_id के अंतर्गत पूरा हुआ। केवल किसी अन्य ब्राउज़र या सत्र में उपभोग किया गया एक्शन टोकन ही ऐसा उत्पन्न करता है, इसलिए मेल लिंक वास्तव में क्लिक किया गया था। नियतात्मक रूप से वैध। |
CANDIDATE | भेजने के समान code_id। बायपास ऐसा ही दिखता है, और वैध समान-ब्राउज़र रीसेट भी ऐसा ही दिखता है। अपने आप में कोई निष्कर्ष नहीं। |
NOT_RESET_FLOW | विंडो में उस उपयोगकर्ता के लिए कोई SEND_RESET_PASSWORD नहीं; पासवर्ड किसी अन्य तरीके से बदला गया (खाता कंसोल, admin API, नामांकन)। Q4 से मिलान करें। |
secs_after_send संदर्भ के लिए मुद्रित किया जाता है। इसे निर्णय के रूप में उपयोग न करें।