Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2026-18963-Exploit — Exploit para Keycloak CVE-2026-18963 que permite a tomada de conta não autenticada via bypass de redefinição de credenciais. Inclui detecção segura, prova não destrutiva, tomada de conta completa, enumeração de nomes de usuário e um laboratório com versões vulneráveis e corrigidas. | Kitploit
Ferramentas/GitHubGitHub/snizi/cve-2026-18963-exploit
Autenticação e AutorizaçãoAnálise de VulnerabilidadesExploraçãoExploração de Aplicações WebTestes de Penetração
GitHubsnizi/cve-2026-18963-exploit

CVE-2026-18963-Exploit

Ver Repositório

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →

Sobre

431251há 1 mêsRevisado pelo Kitploit

Exploit para Keycloak CVE-2026-18963 que permite a tomada de conta não autenticada via bypass de redefinição de credenciais. Inclui detecção segura, prova não destrutiva, tomada de conta completa, enumeração de nomes de usuário e um laboratório com versões vulneráveis e corrigidas.

Compartilhar

CVE-2026-18963 — Bypass de reset-credentials do Keycloak → tomada de conta não autenticada

CVE Affected Python Dependencies

Conhecendo apenas um nome de usuário ou endereço de e-mail, um atacante não autenticado define uma senha arbitrária em qualquer conta do Keycloak. O e-mail de redefinição de senha é enviado à vítima real e nunca é necessário — o atacante nunca lê uma caixa de entrada, nunca clica em um link e não possui nenhuma credencial ou sessão prévia.

Afetados: Keycloak 26.0.0 – 26.7.1. Corrigido na versão 26.7.2.


Estou vulnerável?

Um único comando. Nenhum nome de usuário válido é necessário e sem efeitos colaterais — ele não envia e-mail, não grava em nenhuma conta e para antes da etapa explorável.```bash git clone https://github.com/Snizi/CVE-2026-18963-Exploit cd CVE-2026-18963-Exploit

python3 cve_2026_18963_poc.py
--base https://sso.example.com --realm YOUR_REALM
--client-id account
--redirect-uri https://sso.example.com/realms/YOUR_REALM/account/
--safe-check

Python 3.9+, apenas biblioteca padrão. Nada para instalar.

| Saída | Veredicto | Significado |
|:---:|---|---|
| `0` | 🔴 **VULNERÁVEL** | o portão de e-mail estacionado foi servido — o bug em si |
| `2` | 🟢 **CORRIGIDO** | o fluxo desviou para o login e permaneceu lá (correção #51844 presente) |
| `2` | 🟡 **MITIGADO** | redefinição de credenciais inacessível — *Esqueci a senha* está desativado. **Não é uma correção.** |
| `3` | ⚪ **INCONCLUSIVO** | resposta não reconhecida — **não interprete isso como aprovação** |

Execute por realm — *Esqueci a senha* é uma configuração por realm, e `master` conta.
Detalhes, e por que a verificação não precisa de usuário e não altera nada, em
[§4a](#4a-safe-detection---safe-check--start-here).

**Já sabe que está exposto?** Vá para [remediação](#8-remediation) e
[detecção / caça a ameaças](#9-detection).

### Experimente sem um alvo

O repositório inclui um laboratório que inicia uma versão vulnerável **26.7.1** e uma corrigida **26.7.2**
lado a lado contra um realm idêntico, além de uma caixa de correio para observar o e-mail de redefinição
chegar e permanecer não lido enquanto a conta é assumida:```bash
cd lab && docker compose up -d

python3 ../cve_2026_18963_poc.py --base http://localhost:8080 \
  --realm poc --client-id poc-app --safe-check   # VULNERABLE
python3 ../cve_2026_18963_poc.py --base http://localhost:8100 \
  --realm poc --client-id poc-app --safe-check   # PATCHED

⚠️ Apenas para testes autorizados

Este repositório existe para defensores, respondedores a incidentes e testadores de penetração autorizados. Execute-o contra sistemas que você possui ou para os quais possui permissão por escrito para testar. Tudo aqui vem com um laboratório vulnerável autocontido (lab/), portanto nada externo precisa ser tocado para aprender como a falha funciona. Apontá-lo para infraestrutura de terceiros sem autorização é ilegal na maioria das jurisdições e não é algo que este projeto apoia.

Referências: keycloak#51833 · GHSA-4gv3-mc9p-5wqc · correção keycloak#51844


Conteúdo

  • 1. Causa raiz
  • 2. Versões afetadas (incluindo linhas legadas)
  • 3. O laboratório
  • 4. Utilização
    • 4a. Deteção segura (--safe-check) — comece aqui
    • 4b. Prova não destrutiva (--check)
    • 4c. Assunção total de controlo
    • 4d. Enumeração de nomes de utilizador (--enum)
  • 5. Temas de início de sessão personalizados
  • 6. Lacuna conhecida — PKCE
  • 7. Validação efetuada
  • 8. Remediação
  • 9. Deteção
  • Autor

1. Causa raiz

Duas falhas encadeadas. Nenhuma é explorável isoladamente.

Falha 1 — um sinalizador sem âmbito e persistente

services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java

processAction() — qualquer POST que transporte a chave de formulário tryAnotherWay:```java processor.getAuthenticationSession().setAuthNote( AuthenticationProcessor.AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED, "true"); return createSelectAuthenticatorsScreen(model);

A nota é um **booleano simples, sem registro de qual conjunto de execução a definiu**. Ela é
limpa apenas no ramo que trata um parâmetro `authenticationExecution` enviado. Omita esse parâmetro — como este PoC faz em todo o fluxo — e a flag permanece
definida durante toda a vida da sessão de autenticação.

`processFlow()` — enquanto a flag for verdadeira, a avaliação normal do fluxo é ignorada:```java
if (Boolean.parseBoolean(authSession.getAuthNote(AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED))) {
    String lastExecutionId = authSession.getAuthNote(CURRENT_AUTHENTICATION_EXECUTION);
    if (lastExecutionId != null) {
        AuthenticationExecutionModel executionModel =
            realm.getAuthenticationExecutionById(lastExecutionId);
        if (executionModel != null)
            return createSelectAuthenticatorsScreen(executionModel);   // <-- attacker-usable form
    }
}

It renders a submittable form aimed at whatever execution is currently parked, instead of keeping the session pinned on "waiting for the e-mail".

The glue is processResult() case FORK: — when Send Reset Email fires it stamps CURRENT_AUTHENTICATION_EXECUTION = <reset-credential-email execution id> and forks the browser to the login page. The parked execution is precisely the e-mail gate.

Defect 2 — the e-mail gate never checks the action token

`services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialEmail.java````java @Override public void action(AuthenticationFlowContext context) { context.getUser().setEmailVerified(true); context.success(); }

Unconditional. Nothing verifies that the flow was resumed by a valid action token,
so *reaching* `action()` is treated as equivalent to proving mailbox control.

### The chain```
tryAnotherWay POST            → sticky AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED="true"
submit victim identifier      → mail sent to victim, e-mail execution parked (FORK)
re-enter reset-credentials    → sticky flag serves a form targeting the parked e-mail execution
POST that form                → ResetCredentialEmail.action() → success() → gate bypassed
                              → flow advances to UPDATE_PASSWORD → attacker sets the password

Seis pedidos HTTP, sem autenticação, sem parâmetro authenticationExecution em nenhum momento.

A correção (PR #51844)

  • A nota agora armazena model.getId(), e processFlow() a respeita somente quando ela é igual a CURRENT_AUTHENTICATION_EXECUTION; caso contrário, remove-a. No ataque, os dois diferem (id de choose-user vs. id de e-mail-gate) — exatamente o que o patch detecta, e exatamente o sinal em que --safe-check se baseia.
  • ResetCredentialEmail.action() agora exige context.getUser().getId().equals(authNote(ACTION_TOKEN_USER_ID)) e, caso contrário, falha com INVALID_USER.

2. Versões afetadas (incluindo linhas legadas)

Baixar ferramenta