Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
Herramientas/GitHubGitHub/snizi/cve-2026-18963-exploit
Autenticación y AutorizaciónAnálisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebPruebas de Penetración
GitHubsnizi/cve-2026-18963-exploit

CVE-2026-18963-Exploit

Ver Repositorio
71hace 4 díasAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →

Acerca de

Exploit para Keycloak CVE-2026-18963 que permite la toma de control de cuentas sin autenticación mediante la evasión de reset-credentials. Incluye detección segura, prueba no destructiva, toma de control completa, enumeración de nombres de usuario y un laboratorio con versiones vulnerables y parcheadas.

Compartir

CVE-2026-18963 — Bypass de reset-credentials en Keycloak → toma de control de cuenta no autenticada

CVE Affected Python Dependencies

Conociendo solo un nombre de usuario o dirección de correo electrónico, un atacante no autenticado establece una contraseña arbitraria en cualquier cuenta de Keycloak. El correo de restablecimiento de contraseña se envía a la víctima real y nunca es necesario — el atacante nunca lee una bandeja de entrada, nunca hace clic en un enlace, y no posee ninguna credencial o sesión previa.

Afectado: Keycloak 26.0.0 – 26.7.1. Corregido en 26.7.2.


¿Soy vulnerable?

Un solo comando. No se requiere un nombre de usuario válido, y sin efectos secundarios — no envía correo, no escribe en ninguna cuenta, y se detiene antes del paso explotable.```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

root@kitploit:~
Python 3.9+, solo biblioteca estándar. Nada que instalar.

| Salida | Veredicto | Significado |
|:---:|---|---|
| `0` | 🔴 **VULNERABLE** | se sirvió la puerta de correo estacionada — el bug en sí |
| `2` | 🟢 **PARCHEADO** | el flujo se bifurcó al inicio de sesión y se quedó allí (fix #51844 presente) |
| `2` | 🟡 **MITIGADO** | restablecimiento de credenciales inalcanzable — *Forgot password* está desactivado. **No es un parche.** |
| `3` | ⚪ **NO CONCLUYENTE** | respuesta no reconocida — **no lo interpretes como una aprobación** |

Ejecútalo por realm — *Forgot password* es una configuración por realm, y `master` cuenta.
Detalles, y por qué la comprobación no necesita usuario y no toca nada, en
[§4a](#4a-safe-detection---safe-check--start-here).

**¿Ya sabes que estás expuesto?** Salta a [remediación](#8-remediation) y
[detección / threat hunting](#9-detection).

### Pruébalo sin un objetivo

El repositorio incluye un laboratorio que arranca una versión vulnerable **26.7.1** y una parcheada **26.7.2**
lado a lado contra un realm idéntico, además de un buzón para observar cómo llega el correo de restablecimiento
y permanece sin leer mientras la cuenta es tomada:```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

⚠️ Solo pruebas autorizadas

Este repositorio existe para defensores, respondedores de incidentes y probadores de penetración autorizados. Ejecútalo contra sistemas que poseas o para los que tengas permiso por escrito para probar. Todo lo que hay aquí incluye un laboratorio vulnerable autocontenido (lab/), por lo que no es necesario tocar nada externo para aprender cómo funciona el fallo. Apuntarlo a infraestructura de terceros sin autorización es ilegal en la mayoría de las jurisdicciones y no es algo que este proyecto respalde.

Referencias: keycloak#51833 · GHSA-4gv3-mc9p-5wqc · fix keycloak#51844


Contenido

  • 1. Causa raíz
  • 2. Versiones afectadas (incluidas líneas heredadas)
  • 3. El laboratorio
  • 4. Uso
    • 4a. Detección segura (--safe-check) — empieza aquí
    • 4b. Prueba no destructiva (--check)
    • 4c. Toma de control total
    • 4d. Enumeración de nombres de usuario (--enum)
  • 5. Temas de inicio de sesión personalizados
  • 6. Brecha conocida — PKCE
  • 7. Validación realizada
  • 8. Remediación
  • 9. Detección
  • Autor

1. Causa raíz

Dos defectos encadenados. Ninguno es explotable por sí solo.

Defecto 1 — una bandera sin alcance y persistente

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

processAction() — cualquier POST que lleve la clave de formulario tryAnotherWay:```java processor.getAuthenticationSession().setAuthNote( AuthenticationProcessor.AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED, "true"); return createSelectAuthenticatorsScreen(model);

root@kitploit:~
La nota es un **booleano simple sin registro de a qué conjunto de ejecución pertenece**. Solo se limpia en la rama que maneja un parámetro `authenticationExecution` enviado. Si se omite ese parámetro — como hace este PoC en todo momento —, la marca permanece activa durante toda la vida de la sesión de autenticación.

`processFlow()` — mientras la marca sea verdadera, se omite la evaluación normal del flujo:```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(); }

root@kitploit:~
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 solicitudes HTTP, sin autenticación, sin parámetro authenticationExecution en ningún punto.

La corrección (PR #51844)

  • La nota ahora almacena model.getId(), y processFlow() lo respeta solo cuando es igual a CURRENT_AUTHENTICATION_EXECUTION; de lo contrario, lo elimina. En el ataque, los dos difieren (id de choose-user vs. id de e-mail-gate), exactamente lo que detecta el parche, y exactamente la señal en la que se basa --safe-check.
  • ResetCredentialEmail.action() ahora requiere context.getUser().getId().equals(authNote(ACTION_TOKEN_USER_ID)) y, de lo contrario, falla con INVALID_USER.

2. Versiones afectadas (incluidas líneas heredadas)

LíneaVulnerableCorrección comunitaria
Heredada (Keycloak basado en WildFly, ≤ 17)no afectada—
Quarkus 17 – 25.xno afectada—
26.026.0.0 – 26.0.17ninguna
26.126.1.0 – 26.1.5ninguna
26.226.2.0 – 26.2.16ninguna
26.326.3.0 – 26.3.5ninguna
26.426.4.0 – 26.4.1426.4.15 (etiqueta de backport del proveedor)
26.526.5.0 – 26.5.7ninguna
26.626.6.0 – 26.6.526.6.6 (etiqueta de backport del proveedor)
26.726.7.0 – 26.7.126.7.2

Qué significa "heredada" para este CVE

  • Las versiones heredadas no son automáticamente seguras: son seguras por una razón específica. La nota booleana persistente se introdujo en 26.0.0 mediante el commit 6a9e60bb, que añadió la pantalla de selector de autenticadores "Try another way" al flujo de restablecimiento. Cualquier versión anterior simplemente carece de esa ruta de código. Eso incluye las distribuciones antiguas basadas en WildFly y RH-SSO 7.x, que no se ven afectadas por este error, aunque siguen al final de su ciclo de vida y son vulnerables a muchos otros. Permanecer en una compilación heredada no es una remediación.
  • Las líneas heredadas 26.x son el problema real. 26.7.2 es la única versión corregida publicada para el tren comunitario. Si un despliegue se encuentra en 26.0 – 26.6, no hay una versión de parche en esa línea: la corrección requiere una actualización de versión menor, no una versión puntual. Las etiquetas 26.4.15 / 26.6.6 son backports del proveedor y no son intercambiables con las imágenes comunitarias.
  • Debido a que muchos despliegues de larga duración están fijados a una versión 26.x más antigua por razones de compatibilidad, "estamos completamente parcheados en nuestra línea" es una suposición común e incorrecta aquí. Comprueba la compilación en ejecución, no la política de actualización.

Precondiciones: el reino tiene Forgot password habilitado y su flujo de restablecimiento de credenciales vinculado utiliza el autenticador integrado reset-credential-email.


3. El laboratorio

El repositorio incluye tanto un Keycloak vulnerable como uno parcheado, importando el mismo reino, además de Mailpit para capturar el correo de restablecimiento, de modo que puedas verlo llegar y permanecer sin leer mientras se toma control de la cuenta.```bash cd lab docker compose up -d

root@kitploit:~
| Servicio | URL | Versión |
|---|---|---|
| `kc-vuln` | http://localhost:8080 | 26.7.1 — **vulnerable** |
| `kc-patched` | http://localhost:8100 | 26.7.2 — **control parcheado** |
| `kc-mailpit` | http://localhost:8025 | buzón de la víctima |

Realm `poc`, cliente público `poc-app`, usuario `victim` / `OriginalPassw0rd!`, administrador
de Keycloak `admin` / `admin`.

Fija diferentes builds con `KC_VULN_VERSION` / `KC_PATCHED_VERSION`:```bash
KC_VULN_VERSION=26.5.7 docker compose up -d keycloak-vuln

Entre ejecuciones, lab/reset-victim.sh restaura la contraseña de la víctima (KC=http://localhost:8100 lab/reset-victim.sh apunta a la instancia parcheada).

lab/legit_reset.py realiza un restablecimiento genuino extrayendo el enlace del token de acción de Mailpit y haciendo clic en él. Es la muestra de control para el trabajo de detección en §9 — ejecútalo y el exploit contra el mismo realm, luego compara las trazas.

Teardown: docker compose down -v.


4. Uso

Python 3.9+, solo biblioteca estándar — sin dependencias, se instala en cualquier jump box.``` --base Keycloak base URL (e.g. https://sso.example.com) --realm realm name --client-id any enabled public client with the standard flow --redirect-uri a URI permitted by that client (default http://localhost:9999/callback) --insecure skip TLS verification --verbose log every HTTP request --dump FILE write the response body of a failing step to FILE

root@kitploit:~
`--client-id` puede ser cualquier cliente público habilitado con el flujo estándar. El cliente integrado
`account` existe en todos los realms y es la opción fiable, pero restringe
las URI de redirección, por lo que `--redirect-uri` **debe** ser entonces
`<base>/realms/<realm>/account/` — el valor predeterminado se rechaza y el paso 1 falla.

### 4a. Detección segura (`--safe-check`) — comience aquí

No necesita **ningún nombre de usuario válido** y **no tiene efectos secundarios**. Esta es la sonda que debe usar
cuando no deba perturbar el objetivo.```bash
python3 cve_2026_18963_poc.py \
  --base https://sso.example.com --realm corp \
  --client-id account \
  --redirect-uri https://sso.example.com/realms/corp/account/ \
  --safe-check
SalidaVeredictoSignificado
0VULNERABLEse sirvió la puerta de correo en espera — el propio fallo
2PARCHEADOel flujo se desvió al inicio de sesión y permaneció allí (parche #51844 presente)
2MITIGADOrestablecimiento de credenciales inaccesible — Olvidé mi contraseña está desactivado. No es un parche.
3NO CONCLUYENTErespuesta no reconocida — no lo interpretes como una aprobación

Por qué no necesita usuario y no envía correo. ResetCredentialEmail.authenticate() también se bifurca para un usuario desconocido:```java if (user == null) { context.forkWithSuccessMessage(EMAIL_SENT); return; }

root@kitploit:~
`processResult()` `case FORK:` por lo tanto estaciona `CURRENT_AUTHENTICATION_EXECUTION`
en la ejecución de correo electrónico **aunque no se haya encontrado a nadie** — y no se envía ningún correo,
porque no hay nadie a quien enviarlo. La sonda se detiene en el discriminador y nunca
hace POST a la puerta, por lo que `action()` nunca se ejecuta: sin NPE en el objetivo, sin escritura
de `emailVerified`, sin correo, sin tocar la cuenta.

**Solo se afirma sobre la señal positiva.** VULNERABLE ⟺ el paso 5 devuelve un formulario
todavía dentro de `login-actions/reset-credentials` cuyo `execution` difiere de la ejecución
de elegir usuario. Eso *es* el bug: la nota obsoleta
`AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED` que sirve la puerta de correo estacionada.
Ambas mitades importan — la ruta demuestra que seguimos en el flujo de restablecimiento, el id de
ejecución diferente demuestra que es la puerta de correo y no un re-render.

Cualquier otra cosa **no** se llama parcheada en silencio. PATCHED requiere su propia evidencia
(bifurcado a `login-actions/authenticate` *y* un campo de contraseña presente); todo lo
restante es INCONCLUSIVE y necesita un humano. Un diseño anterior trataba "no es el formulario
de la puerta" como parcheado, lo que convierte silenciosamente cada tema personalizado, página de error, bloqueo
de WAF e intersticial en un certificado de salud falso.

### 4b. Prueba no destructiva (`--check`)

Impulsa toda la cadena pero se detiene en el formulario de Actualizar Contraseña. Alcanzar ese formulario
sin un token de acción es concluyente.```bash
python3 cve_2026_18963_poc.py \
  --base https://sso.example.com --realm corp \
  --client-id account \
  --redirect-uri https://sso.example.com/realms/corp/account/ \
  --victim [email protected] --check

Dos efectos secundarios son inevitables, porque ocurren antes del formulario de contraseña — indícalos en el alcance del compromiso:

  • se envía un correo electrónico de restablecimiento de contraseña a la víctima real (el paso 4 es una solicitud de restablecimiento genuina), y
  • la vulnerable action() establece emailVerified = true en la cuenta.

No se modifica ninguna credencial. Prefiere una cuenta de prueba dedicada.

4c. Toma de control total

Solo para laboratorio o demostración explícitamente autorizada.```bash python3 cve_2026_18963_poc.py
--base http://localhost:8080 --realm poc --client-id poc-app
--victim victim --new-password 'PoCPassw0rd!1'

root@kitploit:~
Salida `0` vulnerable · `2` no explotable · `1` contraseña cambiada pero la
concesión de confirmación falló (apunta `--verify-client-id` a un cliente con
Direct Access Grants).

Completar el flujo también devuelve un **código de autorización OIDC para la víctima**, por lo
que la toma de control es inmediata — no se requiere un segundo inicio de sesión con la nueva contraseña.

### 4d. Enumeración de nombres de usuario (`--enum`)

La misma falla es un oráculo de nombres de usuario, y uno más fuerte de lo que Keycloak normalmente
permite. `ResetCredentialEmail.authenticate()` devuelve deliberadamente un
*"Deberías recibir un correo electrónico en breve"* idéntico para usuarios reales y desconocidos, por lo que
el propio formulario de restablecimiento no se puede usar para enumerar — esa defensa sigue en pie en el paso 4. Se
rompe en el **paso 6**, donde `action()` desreferencia al usuario incondicionalmente
(`context.getUser().setEmailVerified(true)`).

| Identificador | Paso 6 | Veredicto |
|---|---|---|
| usuario real | `200`, llega al formulario de Actualizar Contraseña | VÁLIDO |
| usuario desconocido | `400` (página de error NPE) | INVÁLIDO |```bash
python3 cve_2026_18963_poc.py \
  --base http://localhost:8080 --realm poc --client-id poc-app \
  --enum candidates.example.txt

Nunca cambia una contraseña. Sale con 0 si algún identificador se resolvió, 2 en caso contrario.

Coste por sonda: léelo antes de ejecutarlo. Llegar al oráculo requiere completar el paso 4, así que cada sonda contra una cuenta real envía a esa persona un correo genuino de restablecimiento de contraseña y establece emailVerified = true en su registro. No es una comprobación silenciosa: es visible para el titular de la cuenta y muta sus datos. Una lista de 5.000 nombres son 5.000 correos a personas reales y 5.000 cuentas mutadas.

Úsalo para demostrar que el oráculo existe en un puñado de identificadores para el informe, no para cosechar un directorio. Las salvaguardas son deliberadamente conservadoras:

  • --enum-max N rechaza listas de más de N elementos (por defecto 25)
  • --enum-delay SEC pausa entre sondas (por defecto 2.0)

Elevar cualquiera de ellos debería ser una decisión consciente registrada en las notas del compromiso.

Ángulo para el informe: esto anula un control anti-enumeración que Keycloak implementó a propósito. Merece la pena redactarlo como hallazgo propio junto a la toma de control, y elimina "nuestros nombres de usuario no son adivinables" como factor mitigante.


5. Temas de inicio de sesión personalizados

Cualquier despliegue serio incluye un tema de inicio de sesión personalizado, y los temas personalizados renombran o eliminan los ids de elementos estándar (kc-form-login, kc-reset-password-form, kc-select-credential-form, kc-passwd-update-form). Una herramienta que se base en esos ids reporta un falso negativo precisamente en los despliegues que más importan — este lo hacía, antes de ser reescrito. Los temas vistos en entornos reales usan ids como id="login-form" e incluyen un enlace de ¿olvidó su contraseña? con un href vacío.

Por tanto, esta PoC no se basa en nada que controle un tema:

  • Solo las URLs de acción de los formularios. Cada decisión se toma del action= de los formularios de la página — login-actions/reset-credentials, login-actions/authenticate, login-actions/required-action — y del parámetro de consulta execution dentro de ellos. Esas rutas las genera el propio LoginActionsService de Keycloak, no el tema.
  • Sin ids de elementos. Haz grep al código fuente: no hay ni un solo id kc-* en él.
  • Sin texto de mensajes. Las cadenas de respuesta están localizadas — un realm alemán responde "Reset Credential nicht erlaubt", y buscar coincidencias con "You should receive an email" falla en cualquier realm no inglés.
  • Nunca sigue un enlace temático de "¿Olvidó su contraseña?". El enlace puede estar ausente, vacío, controlado por JavaScript o apuntar a un lugar completamente fuera de Keycloak — nada de eso dice nada sobre si el endpoint es alcanzable. La herramienta construye /realms/<realm>/login-actions/reset-credentials?client_id=…&tab_id=… y lo sondea directamente, tomando tab_id del formulario que la página de inicio de sesión sí exponga.

Si un objetivo sigue devolviendo INCONCLUSIVE, ejecuta con --verbose --dump out.html y lee la respuesta — la herramienta se niega deliberadamente a adivinar.


6. Limitación conocida — PKCE

Un cliente que aplica PKCE rechaza el paso 1 con Missing parameter: code_challenge_method. Esto se reporta como INCONCLUSIVE (salida 3), nunca como un pase. Hasta que llegue el soporte de PKCE, un realm cuyo único cliente público utilizable exija PKCE no puede comprobarse con esta herramienta — prueba con el cliente integrado account, que normalmente no lo aplica.


7. Validación realizada

Cada ejecución siguiente se realiza contra el laboratorio de este repositorio, usando el código tal como se publica.

PruebaObjetivoResultado
--safe-check26.7.1VULNERABLE, salida 0 — la puerta de correo se sirvió (execution ≠ choose-user)
--safe-check26.7.2PARCHEADO, salida 2 — bifurcó al inicio de sesión y se quedó allí
--safe-check, ¿Olvidó su contraseña? desactivado26.7.2MITIGADO, salida 2 — HTTP 400, flujo inalcanzable
Toma de control completa26.7.1salida 0 — contraseña establecida, código OIDC emitido, concesión de contraseña lo confirma
Toma de control completa26.7.2salida 2 — bloqueado en el paso 5, cuenta intacta
--check26.7.1alcanzó UPDATE_PASSWORD; contraseña verificada sin cambios después
--enum26.7.1victim y [email protected] VÁLIDOS, does-not-exist INVÁLIDO
Estado de credenciales tras la toma de control26.7.1nueva contraseña → 200, contraseña antigua → 400
Estado de credenciales tras ejecución bloqueada26.7.2contraseña antigua → 200, contraseña del atacante → 400
Buzón de la víctimaMailpitcorreos de restablecimiento entregados y sin leer; el enlace del token de acción nunca se consulta

Dos hallazgos que merece la pena señalar más allá del texto del aviso:

  1. Las cuentas sin dirección de correo son explotables. ResetCredentialEmail.authenticate() toma la ruta forkWithSuccessMessage cuando user.getEmail() es null, que igualmente aparca la ejecución mediante case FORK:. Lo mismo ocurre con un fallo de envío SMTP — un servidor de correo roto o ausente no es una mitigación. Esto importa directamente para realms federados con AD/LDAP, donde las cuentas frecuentemente no tienen atributo de correo.
  2. Completar el flujo inicia sesión del atacante como la víctima. La redirección final lleva un código de autorización OIDC válido, así que la cuenta queda comprometida en el momento en que se envía el formulario de contraseña.

El MFA no es una mitigación. El flujo de restablecimiento de credenciales por defecto no contiene ningún paso OTP, y una vez superado, el atacante puede eliminar los factores registrados de la víctima.


8. Remediación

Solución: actualiza. 26.7.2 para builds de la comunidad, o la etiqueta de backport del proveedor que coincida con tu suscripción. Todo lo demás es un parche provisional.

Mitigaciones provisionales, de mejor a peor:

  1. Desactiva ¿Olvidó su contraseña? por realm (Realm settings → Login). Confirmado como efectivo — el flujo devuelve HTTP 400 y no se puede entrar. Comprueba todos los realms, incluido master.
  2. Desactiva la ejecución Reset Password en el flujo de restablecimiento de credenciales vinculado. Funciona, pero la página de inicio de sesión sigue ofreciendo el enlace, así que la experiencia de usuario es pobre. Útil donde un tema personalizado ignora el interruptor del realm.
  3. Añade un autenticador obligatorio (OTP/WebAuthn) después del paso de correo en el flujo de restablecimiento. Esto no cierra la evasión — solo limita la toma de control completa a cuentas que realmente hayan inscrito ese factor.

Los realms cuyo flujo de restablecimiento vinculado es totalmente personalizado y nunca invoca reset-credential-email no son explotables por esta vía.


9. Detección

Keycloak no emite ningún evento de "token de acción omitido", así que la detección es heurística. Ejecuta lab/legit_reset.py junto al exploit para generar ambos rastros y compararlos.

  • Registros del proxy inverso / ingress — la señal más fuerte. Un restablecimiento legítimo muestra un GET /login-actions/action-token?... (la víctima haciendo clic en el correo) antes del cambio de contraseña. La evasión no tiene ese GET. En su lugar muestra un POST a login-actions/reset-credentials cuyo cuerpo contiene tryAnotherWay, seguido de un segundo POST a la misma ruta con un cuerpo vacío, y luego el formulario de contraseña. Un POST con tryAnotherWay dentro del flujo de restablecimiento no es algo que la UI estándar produzca en uso normal.
  • Eventos de administración: SEND_RESET_PASSWORD seguido de UPDATE_PASSWORD compartiendo el mismo code_id en pocos segundos — submilisegundo en el laboratorio. Un usuario con el correo ya abierto también puede parecer rápido, así que corrobora con los registros del proxy.
  • Cuentas cuyo emailVerified cambió a true sin ningún evento VERIFY_EMAIL correspondiente son un indicador de apoyo útil, y uno que el atacante no puede evitar dejar.

La ausencia de eventos no prueba nada si el registro de eventos o su retención estaban desactivados. Comprueba la ventana de retención antes de concluir que un despliegue no fue alcanzado.


Autor

Snizi — github.com/Snizi — [email protected]

Publicado bajo la Licencia MIT. Se aceptan issues y PRs — especialmente soporte de PKCE y peculiaridades adicionales de temas del mundo real.

Descargar herramienta