Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

FeedContattoPrivacy© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
KeycloakESC — Lab Docker riproducibile + PoC: escalation da Keycloak manage-users a realm-admin tramite ruoli compositi (variante CVE-2026-94000). Convalidato su 26.8.1. | Kitploit
Strumenti/GitHubGitHub/secfathy/keycloakesc
Autenticazione e AutorizzazioneEscalation di PrivilegiAnalisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebPenetration TestingGestione Identità e Accessi (IAM)Lab e Pratica
GitHubsecfathy/keycloakesc

KeycloakESC

Lab Docker riproducibile + PoC: escalation da Keycloak manage-users a realm-admin tramite ruoli compositi (variante CVE-2026-94000). Convalidato su 26.8.1.

313 giorni faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi
Vedi Repository

Keycloak composite map-role privilege escalation

Un laboratorio Docker riproducibile e PoC per un percorso di escalation dei privilegi nell'API REST di amministrazione di Keycloak: un amministratore delegato che possiede solo manage-users può elevare se stesso (o qualsiasi utente o gruppo) a realm-admin completo mappando un ruolo composito il cui nome è ordinario ma i cui figli includono realm-management/realm-admin.

Confermato end-to-end sull'immagine ufficiale quay.io/keycloak/keycloak:26.8.1.

⚠️ Solo ricerca autorizzata. Tutto viene eseguito su un Keycloak usa e getta su localhost. Non puntare il PoC verso sistemi che non sei esplicitamente autorizzato a testare.

  • Il problema (causa radice)
  • Proof of concept
  • Esecuzione verificata
  • Remediation

Il problema (causa radice)

Keycloak 26.8.1 ha rafforzato il group join (CVE-2026-94000): un amministratore con manage-users non può più aggiungere un utente a un gruppo che concede transitivamente ruoli di amministrazione realm-management. GroupUtils.checkAdminGroupRoles percorre i ruoli del gruppo ricorsivamente e chiama requireMapRole su ogni ruolo amministrativo annidato:

private static void requireMapRoleRecursive(RoleModel role, AdminPermissionEvaluator auth, Set<String> visited) {
    if (!visited.add(role.getId())) return;
    if (AdminRoles.isAdminRole(role)) auth.roles().requireMapRole(role);   // checks nested admin roles
    if (role.isComposite()) role.getCompositesStream().forEach(child -> requireMapRoleRecursive(child, auth, visited));
}

La stessa ricorsione non è mai stata aggiunta agli endpoint di mappatura dei ruoli. Quando un ruolo viene mappato direttamente su un utente o un gruppo, il server controlla solo il ruolo inviato:

// RoleMapperResource.addRealmRoleMappings — mounted on BOTH users and groups
for (RoleRepresentation role : roles) {
    RoleModel roleModel = realm.getRole(role.getName());
    auth.roles().requireMapRole(roleModel);   // posted role only — children never inspected
    roleMapper.grantRole(roleModel);
}

E il controllo dei privilegi stesso si basa sul nome del ruolo, non sul suo contenuto. In RolePermissionsV2.canMapRole, un ruolo è considerato privilegiato solo quando il suo container è realm-management/master e il suo nome è presente in AdminRoles.ALL_ROLES:

public boolean canMapRole(RoleModel role) {
    if (isRealmAdminRole(role)) { ... }                 // isRealmAdminRole = container + ALL_ROLES.contains(name)
    if (root.hasOneAdminRole(AdminRoles.MANAGE_USERS))  // manage-users may map ANY non-admin-named role
        return true;
    ...
}

Quindi un composite chiamato sneaky-composite che racchiude realm-management/realm-admin supera il controllo — il suo nome non è in ALL_ROLES, e i suoi figli non vengono mai percorsi. La lacuna coinvolge tre endpoint:

  • RoleMapperResource.addRealmRoleMappings — utenti e gruppi
  • ClientRoleMappingsResource.addClientRoleMapping — ruoli client su qualsiasi client

Effetto netto: il payload privilegiato (un composite che racchiude realm-admin) deve solo esistere — creato da un admin reale, da un'importazione di realm o da un processo precedente. manage-users può quindi assegnarlo, cosa che il modello di minaccia di CVE-2026-94000 non aveva mai previsto.

Varianti di attacco

#VariantePerché funziona
AAuto-mappare sneaky-composite → realm-adminil controllo sul nome non intercetta il composite
BMappare outer-sneaky annidato (→ sneaky-composite → realm-admin) su un utentela profondità non viene verificata
CMappare un ruolo client su un client non-admin (spa/hidden-ra → realm-admin)ClientRoleMappingsResource usa lo stesso controllo
DMappare il composite su un gruppo che ha già membriAPI diversa dal join; i membri esistenti escalano senza alcun join

Proof of concept

Requisiti: Docker + Docker Compose v2, e curl + jq sull'host.

cp .env.example .env     # optional: pin KC_VERSION (default 26.8.1)
make up                  # start Keycloak + auto-bootstrap the vulnerable realm `app`
make logs                # wait for "Lab realm 'app' is ready"

make check               # non-destructive detection (maps, then immediately unmaps)
make exploit             # Attack A: self-escalate limited-admin -> realm-admin
make all                 # full chain: check + A + B + C + D
make reset               # undo every escalation (keep the lab running)
make clean               # tear everything down

Il container one-shot bootstrap costruisce lo scenario tramite l'API REST di amministrazione, poi termina:

OggettoScopo
limited-admin / limitedpassAttaccante — possiede solo manage-users
alice / bob / carol / daveUtenti vittima
sneaky-composite (ruolo realm)Composito → realm-management/realm-admin
outer-sneaky (ruolo realm)Composito → sneaky-composite (un salto extra)
client spa + ruolo spa/hidden-raRuolo client non-admin → realm-admin
client confidential (confsecret)Obiettivo di impatto lettura-segreti
gruppo helpdesk (alice è membro)Obiettivo dell'attacco di mappatura dei gruppi

Il PoC risolve gli ID dei ruoli nel modo in cui un chiamante con manage-users può effettivamente fare — tramite gli endpoint .../role-mappings/.../available — perché a quell'account è negato l'accesso a GET /roles/{name} e GET /clients (403) ma non alle liste available. Questo mantiene lo script una riproduzione onesta dal punto di vista di un attaccante a basso privilegio.

Convalidare una correzione

Punta il lab su una build corretta; un server corretto deve restituire 403 su ogni fase di mappatura pur consentendo ancora la normale mappatura dei ruoli non-admin:

KC_VERSION=<patched-tag> docker compose up -d --force-recreate
make check        # expect: NOT vulnerable

Esecuzione verificata

Contro quay.io/keycloak/keycloak:26.8.1 (trascrizione completa in docs/demo.txt, dettagli in VALIDATION.md):

PassoAzioneRisultato
Baselinelimited-admin POST /roles403 (privilegi effettivamente bassi)
checkmappare sneaky-composite su se stesso (poi rimuovere la mappatura)204 → VULNERABILE
Aself-map sneaky-composite → realm-admin → creare ruolo / estrarre email utenti204 / 201 / 200
Bouter-sneaky annidato su bob → bob crea ruolo204 / 201
Cspa/hidden-ra su carol → carol crea ruolo204 / 201
Dmappare il wrapper su helpdesk → il membro esistente alice crea ruolo204 / 201
Controllo Dmanage-users aggiunge un nuovo membro a helpdesk403 (fix CVE-2026-94000 intatto)

Il controllo D dimostra l'asimmetria: l'aggiunta a un gruppo è bloccata, ma la mappatura dello stesso composite sul gruppo (o su un utente/client) non viene percorsa e restituisce 204.


Remediation

Scarica lo strumento