
Keycloak 26.8.1 Medio 6.6 Autenticación remota autenticada residual. Un administrador de mesa de ayuda con manage-users puede fijarse a sí mismo un compuesto preconstruido de manage-realm y luego leer el documento completo del realm. Requiere que ese compuesto ya exista. PoC en loopback.
Una cuenta de help-desk que solo debería restablecer contraseñas y crear usuarios puede promocionarse a sí misma. Alguien con el rol manage-users de Keycloak encuentra un cargo residual en el realm (un rol compuesto que incluye silenciosamente manage-realm), fija ese cargo en su propia cuenta y luego lee el documento completo del realm que le había sido ocultado una petición antes. No puede crear ese compuesto. Un administrador real del realm tiene que haberlo construido primero. Este es el hermano de mapeo de roles de CVE-2026-94000, que cerró el mismo truco en la unión a grupos.
Clase: Residuo de autenticación
Alcance: Remoto (manage-users autenticado)
Keycloak 26.8.1 (24ed1dad) - Red Hat
| ID | aún sin CVE |
| Clase | Residuo de autenticación |
| Alcance | Remoto (Admin REST autenticado; requiere manage-users más un compuesto preconstruido) |
| CWE | CWE-269 / CWE-266 |
| CVSS | Medio: 6.6 CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:H/I:H/A:H |
| Producto | Keycloak |
| Afectado | 26.8.1 (24ed1dadf3f246a555adb6d3d4a99e9b3003fb3b); imagen quay.io/keycloak/keycloak:26.8.1 |
| Autenticación | admin delegado con realm-management / manage-users. FGAP v2 es el evaluador por defecto. |
| Licencia | GNU Affero GPL v3.0 |
| Laboratorio | solo 127.0.0.1:18082 |
Requiere una cuenta de Keycloak existente que ya posea manage-users, y un rol de realm o de cliente cuyo propio nombre no sea un rol de administrador y cuyos compuestos incluyan manage-realm o realm-admin. No necesita manage-realm en el token. No puede crear ese compuesto. La asignación directa de un rol llamado manage-realm / realm-admin sigue siendo rechazada.
| Privilegio | Método / sink | Reconocimiento / integridad / disponibilidad | Probado en laboratorio o inferido |
|---|---|---|---|
| Mapear un compuesto no administrativo sobre uno mismo | POST /admin/realms/{realm}/users/{id}/role-mappings/realm con el id y nombre del compuesto | Integridad (concesión de rol) | Probado en laboratorio. HTTP 204. Testigo kcr02m7q4 |
| Misma concesión sobre un rol de cliente | POST /admin/realms/{realm}/users/{id}/role-mappings/clients/{client} | Integridad | Código fuente. Mismo canMapRole en ClientRoleMappingsResource.java:184 |
| Leer el documento completo del realm con el mismo token de acceso | GET /admin/realms/{realm} tras el mapeo | Reconocimiento | Probado en laboratorio. Antes: HTTP 200 parcial (sin atributos, sin accessTokenLifespan). Después: HTTP 200 completo, atributo plantado presente |
Usar manage-realm anidado en llamadas administrativas posteriores | UserAdapter.hasRole recorre los compuestos; KeycloakIdentity.hasClientRole confía en el modelo de usuario | Integridad | Inferido del código fuente. El oráculo del laboratorio es el GET completo del realm |
realm-admin anidado cuando ese es el compuesto | Mismo recorrido | Integridad | Inferido. El laboratorio usó manage-realm |
| Control negativo | Un segundo usuario con manage-users que no mapea el compuesto | n/a | Probado en laboratorio. El GET de control permanece parcial |
Sigue cerrado en este residuo
| Eje | Método / sink | Por qué está cerrado |
|---|---|---|
| Integridad | Mapeo directo de manage-realm / realm-admin / otros AdminRoles.ALL_ROLES | RolePermissionsV2.isRealmAdminRole sigue rechazándolo |
| Integridad | Crear el compuesto que incluye un rol de administrador | canMapComposite sigue llamando a checkAdminRoles |
| Integridad | Unirse a un grupo cuyo compuesto incluye un rol de administrador | CVE-2026-94000 recorre los compuestos en GroupUtils.checkAdminGroupRoles |
| Integridad | Crear un usuario que ya está en ese grupo | Mismo recorrido en UsersResource.createUser |
| Reconocimiento | Admin REST anónimo | Requiere un token de manage-users |
| Integridad | RCE en el host, realm-admin creando realm-admin | Fuera de clase |
GET /admin/realms/{realm} no devuelve HTTP 403 para manage-users. Ese rol es en sí mismo un rol de administrador, por lo que el servidor devuelve 200 con un documento parcial. Lo que queda son los campos que solo aparecen después de que se mapea el compuesto.
Fijé Keycloak 26.8.1. Los permisos de administrador de grano fino v2 están activados por defecto. RolePermissionsV2.canMapRole devuelve true para cada rol que falla isRealmAdminRole y nunca recorre los compuestos. La corrección de CVE-2026-94000 los recorre solo en la ruta de grupos.
Errores ya registrados: tratar isRealmAdminRole de v1 como la comprobación activa (v2 lo anula); esperar HTTP 403 en el GET del realm antes de la concesión (el resultado real es un 200 parcial); volver a presentar CVE-2026-94000 (unión de grupos, ya cerrado); una reverse shell. Teatro.
python3 keycloak-manage-users-composite-Abraxas-Labs.py
o:
cd lab
./run.sh
Dirígete solo a http://127.0.0.1:18082. Imagen quay.io/keycloak/keycloak:26.8.1. Se requiere Docker. El lanzador hace chdir a lab/ y ejecuta run.sh.
IOC image=quay.io/keycloak/keycloak:26.8.1 label-version=26.8.1
IOC serverinfo-version=26.8.1
IOC admin-composite=manage-realm
IOC limited-direct=manage-users
IOC control-direct=manage-users
IOC before-status=200 witness=0 full=0
IOC available=sneaky-composite
IOC post-status=204
IOC after-get attempt=1 status=200 witness=1 full=1
IOC control-status=200 witness=0 full=0 same-token=1
SUCCESS KC-H02-ROLEMAP kcr02m7q4
Recorrer los composites en RolePermissionsV2.canMapRole de la misma manera que GroupUtils.checkAdminGroupRoles ya lo hace para la unión a grupos. Un rol que incluye manage-realm o realm-admin es un rol de administrador incluso cuando su propio nombre no lo es.
24ed1dadf3f246a555adb6d3d4a99e9b3003fb3b)RolePermissionsV2.canMapRole (RolePermissionsV2.java:59-61)RoleMapperResource.addRealmRoleMappings (RoleMapperResource.java:289-290)GNU Affero GPL v3.0. Consulte LICENSE. Solo laboratorio de loopback. Sin garantía.
Abraxas Labs [email protected]
Por favor, acredite el CVE a Abraxas Labs.