Módulo 7 de 10

Módulo 7: Autenticación y gestión de sesiones

Módulo 7: Autenticación y gestión de sesiones

La autenticación y la gestión de sesiones son el corazón de la seguridad en cualquier aplicación web. Cuando un sistema falla al verificar quién eres o al proteger la sesión que acredita esa identidad, las consecuencias van desde el acceso no autorizado a cuentas de usuarios hasta la toma completa de la plataforma. Según OWASP A07:2025 — Authentication Failures (edición vigente del Top 10 desde 2025), este tipo de vulnerabilidad afecta a millones de aplicaciones en producción y figura en el Top 10 desde sus primeras ediciones.

En este módulo trabajarás los fallos más comunes de forma técnica y práctica, siempre dentro de entornos de laboratorio legales. Aprenderás a identificarlos, explotarlos en lab y, lo más importante, a corregirlos.

Aviso legal y ético (obligatorio): Todas las técnicas de este módulo deben practicarse exclusivamente en laboratorios propios o plataformas de entrenamiento autorizadas (OWASP Juice Shop, DVWA, PortSwigger Web Security Academy, máquinas virtuales propias). Aplicar estas técnicas contra sistemas ajenos sin autorización escrita constituye un delito tipificado en el artículo 197 bis del Código Penal español, con penas de prisión de seis meses a dos años. Conocer el ataque es el primer paso para defenderlo — úsalo de forma responsable.

Qué aprenderás

  • Cómo funcionan los ataques de fuerza bruta y credential stuffing y cómo limitarlos.
  • Técnicas de enumeración de usuarios a través de mensajes de error y diferencias de tiempo de respuesta.
  • Fallos en recuperación de contraseña y en la implementación de MFA, incluyendo MFA resistente a phishing (passkeys / WebAuthn / FIDO2).
  • Vulnerabilidades de gestión de sesiones: fijación de sesión, predicción de ID, expiración y logout.
  • Estructura y riesgos de los JWT: el ataque alg:none, secretos débiles y confusión de algoritmo.
  • Pasos de laboratorio reproducibles en Juice Shop y PortSwigger Web Security Academy.
  • Contramedidas concretas para cada fallo, listas para implementar en producción.

OWASP A07:2025 — Authentication Failures

En el OWASP Top 10:2025 (edición vigente), esta categoría se mantiene en la séptima posición y pasa a llamarse simplemente Authentication Failures (el nombre se acortó respecto a «Identification and Authentication Failures» de 2021). Agrupa 36 CWE relacionadas con fallos al verificar la identidad y al gestionar credenciales y sesiones. Las CWE más representativas según OWASP son:

  • CWE-287: Autenticación incorrecta.
  • CWE-384: Fijación de sesión.
  • CWE-297: Validación incorrecta del certificado con discrepancia de host.
  • CWE-259 / CWE-798: Uso de contraseñas y credenciales embebidas (hard-coded).

Si estás preparando certificaciones como la eJPT u OSCP, dominar esta categoría es imprescindible: aparece en casi todos los CTF y pentests reales. También es terreno habitual en programas de bug bounty donde los reportes de autenticación rota siguen siendo de los mejor remunerados.

Fallos de autenticación

Fuerza bruta y ausencia de limitación de intentos

Un ataque de fuerza bruta consiste en probar contraseñas de forma sistemática hasta encontrar la correcta. Sin un mecanismo de limitación de intentos (rate limiting) o bloqueo de cuenta, un atacante puede automatizar miles de peticiones por minuto. Herramientas como Burp Suite Intruder, Hydra o ffuf hacen este proceso trivial.

La diferencia entre fuerza bruta y credential stuffing es importante:

Técnica Datos de entrada Objetivo
Fuerza bruta pura Wordlist o combinaciones exhaustivas Encontrar la contraseña de un usuario conocido
Credential stuffing Pares usuario:contraseña de filtraciones previas Reutilización de credenciales en otro servicio
Password spraying Una o pocas contraseñas comunes contra muchos usuarios Evitar bloqueos por intentos fallidos

El credential stuffing es especialmente peligroso porque explota la reutilización de contraseñas: si un usuario usa la misma contraseña en cinco servicios y uno de ellos sufre una brecha, los otros cuatro quedan expuestos. Bases de datos como Have I Been Pwned agrupan miles de millones de credenciales filtradas públicamente.

Enumeración de usuarios

Muchas aplicaciones revelan indirectamente si un nombre de usuario existe o no. Los dos vectores más frecuentes son:

  1. Mensajes de error diferentes: «Usuario no encontrado» vs. «Contraseña incorrecta». El primer mensaje confirma que el usuario no existe; el segundo confirma que sí existe.
  2. Diferencia en tiempo de respuesta: Algunos backends aplican la verificación de contraseña (costosa en tiempo, por el hashing) solo si el usuario existe. Si el tiempo de respuesta es perceptiblemente mayor, el usuario es válido.

PortSwigger ofrece laboratorios específicos para practicar ambas variantes: Username enumeration via different responses y Username enumeration via response timing.

Contraseñas débiles y políticas insuficientes

Permitir contraseñas como 123456, password o admin es un fallo de diseño básico. La versión vigente del estándar NIST SP 800-63B-4 (2024) establece requisitos concretos:

  • Longitud mínima de 15 caracteres cuando la contraseña es el único factor de autenticación; se permite un mínimo de 8 caracteres solo cuando forma parte de un proceso MFA. Los verificadores deberían admitir contraseñas de al menos 64 caracteres.
  • No imponer reglas de composición (mezclas obligatorias de mayúsculas, números o símbolos): el estándar lo prohíbe explícitamente porque empuja a los usuarios a patrones predecibles.
  • No forzar caducidad periódica: solo se obliga a cambiar la contraseña si hay evidencia de que ha sido comprometida.
  • Verificar contra corpus de filtraciones: las contraseñas nuevas deben compararse con listas de credenciales comprometidas conocidas y rechazarse si coinciden.

Recuperación de contraseña insegura

Los flujos de «olvidé mi contraseña» concentran una cantidad desproporcionada de vulnerabilidades:

  • Preguntas de seguridad predecibles: «¿Nombre de tu primera mascota?» — información pública en redes sociales.
  • Tokens de recuperación predecibles o de corta entropía: tokens de 4 o 6 dígitos numéricos adivinables por fuerza bruta.
  • Tokens sin expiración: un enlace de recuperación que no caduca puede ser utilizado meses después.
  • Falta de invalidación al usar: un token de un solo uso que puede reutilizarse.

Fallos en la implementación de MFA

La autenticación multifactor (MFA) es una defensa sólida, pero su implementación puede presentar grietas:

  • MFA bypass por lógica rota: la aplicación verifica el primer factor (contraseña) y crea la sesión antes de verificar el segundo factor. Si el usuario navega directamente a /dashboard tras el primer factor, puede saltarse el MFA.
  • Códigos TOTP sin protección de fuerza bruta: un código de 6 dígitos tiene solo un millón de combinaciones. Sin rate limiting, es adivinable en segundos.
  • Recuperación de cuenta que anula el MFA: si el flujo de recuperación permite cambiar el método de autenticación sin verificar el segundo factor, el MFA se vuelve inútil.
  • Segundos factores débiles frente a phishing: los OTP por SMS o por email pueden interceptarse, y el SMS añade el riesgo de SIM swapping (clonado o secuestro fraudulento de la línea). Tanto PortSwigger como NIST SP 800-63B advierten de estas debilidades y separan ya los autenticadores resistentes a phishing del resto.

El laboratorio de PortSwigger 2FA broken logic demuestra el fallo de verificación de lógica de forma práctica; la sección Vulnerabilities in multi-factor authentication incluye además labs de 2FA simple bypass y de fuerza bruta del código 2FA.

Fallos de gestión de sesiones

Cookies de sesión: configuración incorrecta

La sesión de un usuario autenticado se mantiene, habitualmente, mediante una cookie con el identificador de sesión. Tres atributos son críticos para su seguridad:

Atributo Protege contra Ejemplo de cabecera
HttpOnly Robo mediante XSS (document.cookie) Set-Cookie: sessid=abc; HttpOnly
Secure Transmisión por HTTP sin cifrar (sniffing) Set-Cookie: sessid=abc; Secure
SameSite=Strict Ataques CSRF (peticiones cruzadas) Set-Cookie: sessid=abc; SameSite=Strict

La ausencia de cualquiera de estos atributos abre vectores de ataque adicionales que se combinan con los fallos de autenticación.

Fijación de sesión (session fixation)

En un ataque de fijación de sesión, el atacante fuerza al navegador de la víctima a usar un identificador de sesión conocido por él antes de que la víctima se autentique. El flujo es:

  1. El atacante obtiene un ID de sesión válido (no autenticado) del servidor.
  2. Engaña a la víctima para que visite la aplicación con ese ID (por ejemplo, mediante un enlace con el parámetro ?JSESSIONID=xyz).
  3. La víctima se autentica. Si la aplicación no regenera el ID de sesión tras el login, el atacante ahora tiene acceso a la sesión autenticada.

Referencia técnica: OWASP — Session Fixation.

Entropía y predicción del ID de sesión

Un identificador de sesión debe ser:

  • Suficientemente largo: al menos 128 bits de entropía.
  • Generado con un CSPRNG (generador pseudoaleatorio criptográficamente seguro), no con rand(), Math.random() o marcas de tiempo.
  • Único e impredecible: si el ID es secuencial (sess_1001, sess_1002…) o derivado de datos predecibles, es trivialmente adivinable.

Herramientas como Burp Suite Sequencer permiten capturar una serie de tokens de sesión y analizar estadísticamente su entropía real, detectando si el generador del servidor es débil.

Expiración de sesión y logout seguro

Una sesión que no expira es un riesgo permanente. Las buenas prácticas son:

  • Tiempo de inactividad: invalidar la sesión tras un período de inactividad (típicamente 15-30 minutos para apps sensibles).
  • Expiración absoluta: incluso si hay actividad, forzar re-autenticación tras un período máximo.
  • Logout efectivo en el servidor: eliminar el registro de sesión en el backend, no solo borrar la cookie en el cliente. Si solo se borra la cookie, el token sigue siendo válido y puede reutilizarse si fue capturado previamente.

Introducción a JWT y sus riesgos

Los JSON Web Tokens (JWT) son ampliamente usados para autenticación sin estado (stateless), especialmente en APIs REST y arquitecturas de microservicios. Un JWT tiene tres partes separadas por puntos, codificadas en Base64url:

header.payload.signature

Ejemplo:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0IiwicmI6ImFkbWluIn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
  • Header: indica el algoritmo de firma (alg) y el tipo (typ). Ejemplo: {"alg":"HS256","typ":"JWT"}.
  • Payload: contiene las claims (afirmaciones), como el ID de usuario, el rol, o la expiración (exp). No está cifrado, solo codificado en Base64.
  • Signature: se genera firmando header.payload con el secreto del servidor o la clave privada. Es lo que garantiza la integridad.

Ataque alg:none

Algunas implementaciones aceptan el valor especial "alg":"none" en el header, que indica un JWT sin firma. Un atacante puede modificar el payload (por ejemplo, cambiar "role":"user" a "role":"admin"), establecer "alg":"none" y eliminar la firma. Si la librería del servidor lo acepta, el token manipulado será válido.

# Decodificar la parte header del JWT:
echo "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" | base64 -d
# Output: {"alg":"HS256","typ":"JWT"}

# Un token con alg:none tiene firma vacía:
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiIxMjM0Iiwicm9sZSI6ImFkbWluIn0.

También pueden intentarse variaciones de capitalización (None, NONE, nOnE) para evadir filtros basados en comparación de cadenas. Referencia: PortSwigger — JWT attacks y OWASP WSTG — Testing JSON Web Tokens.

Secreto débil en JWT (HS256)

Cuando el algoritmo es HS256, la firma se genera con un secreto compartido. Si ese secreto es corto o predecible (secret, password, el nombre de la app…), puede crackearse offline con herramientas como Hashcat o jwt-cracker:

# Crackear el secreto de un JWT con Hashcat (modo 16500):
hashcat -a 0 -m 16500 token.jwt wordlist.txt

Una vez obtenido el secreto, el atacante puede firmar tokens arbitrarios con el rol que desee.

Confusión de algoritmo (algorithm / key confusion)

Este ataque ocurre cuando el atacante consigue que el servidor verifique la firma con un algoritmo distinto del previsto por los desarrolladores. El caso clásico: un servidor que firma con RS256 (clave asimétrica: privada para firmar, pública para verificar), pero cuya librería, mal configurada, también acepta HS256. Si el atacante obtiene la clave pública (que no es secreta), puede firmar un token con HS256 usando esa clave pública como secreto HMAC; un servidor vulnerable la usará para verificar y dará el token por válido, permitiendo forjar claims arbitrarias sin conocer la clave privada.

PortSwigger dedica laboratorios específicos a este vector, incluyendo una variante en la que la clave pública no está expuesta y debe derivarse a partir de dos tokens: Algorithm confusion attacks. La defensa es que el backend fije y valide un único algoritmo esperado, sin permitir que el header alg del token determine el método de verificación.

Laboratorio paso a paso

Lab A — Enumeración de usuarios y fuerza bruta con Burp Intruder (PortSwigger Web Security Academy)

Este laboratorio está basado en el ejercicio oficial Username enumeration via different responses de PortSwigger. Accede a tu instancia del lab en la plataforma.

  1. Abre Burp Suite y activa el proxy en tu navegador (o usa el navegador integrado de Burp).
  2. Navega al formulario de login del lab e introduce credenciales ficticias (testuser / testpass). Captura la petición POST.
  3. En Burp, haz clic derecho sobre la petición → Send to Intruder.
  4. En la pestaña Positions, selecciona el modo Sniper. Rodea únicamente el valor del parámetro username con marcadores: username=§testuser§.
  5. En la pestaña Payloads, carga la lista de candidatos de PortSwigger (auth-lab-usernames).
  6. Lanza el ataque. Ordena los resultados por Length: una respuesta tendrá longitud diferente porque el mensaje de error cambia de «Invalid username» a «Incorrect password».
  7. Anota el nombre de usuario válido. Ahora repite el proceso con ese usuario fijo y la lista de contraseñas, marcando el campo password.
  8. El request con código 302 (redirección) indica login exitoso. Accede a la cuenta para completar el lab.

Qué observas: el servidor revela la existencia de usuarios a través de mensajes de error distintos. Esta sola diferencia reduce el espacio de búsqueda de O(usuarios × contraseñas) a O(usuarios) + O(contraseñas).

Lab B — Fuerza bruta en OWASP Juice Shop

OWASP Juice Shop es una aplicación web intencionalmente vulnerable ideal para practicar. Instálala localmente con Docker:

# Levantar Juice Shop en local:
docker pull bkimminich/juice-shop
docker run -d -p 3000:3000 bkimminich/juice-shop
# Accede en: http://localhost:3000
  1. Navega a http://localhost:3000/#/login.
  2. Intercepta la petición POST de login con Burp. Observa los parámetros email y password.
  3. Envía la petición a Burp Intruder. Marca ambos campos como posiciones de payload → modo Cluster Bomb (combina dos listas independientes).
  4. Carga como lista de emails usuarios típicos de Juice Shop (el usuario admin es admin@juice-sh.op). Para la contraseña, usa una wordlist pequeña como rockyou-mini.txt.
  5. Observa la respuesta: un código 200 con un campo authentication.token en el JSON indica login exitoso.
  6. Verifica que Juice Shop no implementa rate limiting por defecto: puedes enviar cientos de peticiones sin bloqueo.

Reflexión: esta vulnerabilidad existe porque la aplicación no limita intentos fallidos ni añade delays progresivos. En producción, este fallo permitiría comprometer cuentas de usuarios reales en minutos.

Lab C — Manipulación de cookie de sesión (Burp Repeater)

  1. En Juice Shop, autentica con admin@juice-sh.op y la contraseña por defecto (admin123).
  2. Captura en Burp la cookie de sesión (token) asignada. Es un JWT.
  3. Copia el valor del JWT y analízalo en jwt.io. Observa el payload: contiene el campo email y el algoritmo en el header.
  4. Modifica el payload para cambiar el email por otro usuario conocido (por ejemplo bender@juice-sh.op).
  5. Prueba a enviar una petición a la API con el token modificado. Observa si el servidor valida la firma o solo decodifica el payload.
  6. En labs de PortSwigger sobre JWT (JWT attacks), practica específicamente el ataque alg:none siguiendo las instrucciones del laboratorio.

Cómo prevenirlo

Políticas de contraseña robustas

  • Exigir un mínimo de 15 caracteres para contraseñas usadas como único factor (mínimo de 8 solo dentro de MFA), sin reglas de composición arbitrarias: el factor crítico es la longitud, conforme a NIST SP 800-63B-4.
  • Comprobar las contraseñas nuevas contra bases de datos de credenciales filtradas. La API de Have I Been Pwned (api.pwnedpasswords.com) permite hacerlo sin enviar la contraseña completa (modelo k-anonymity con SHA-1 parcial).
  • Almacenar contraseñas con algoritmos de hashing diseñados para ello: bcrypt, Argon2id o scrypt. Nunca MD5, SHA-1 o SHA-256 sin sal.

Rate limiting y bloqueo de cuentas

  • Implementar CAPTCHA o delays progresivos tras 3-5 intentos fallidos.
  • Bloquear temporalmente la cuenta tras 10 intentos fallidos (con notificación al usuario legítimo).
  • Usar rate limiting por IP con herramientas como fail2ban, módulos de nginx/Apache o librerías específicas (express-rate-limit en Node.js, Django Ratelimit en Python).
  • Registrar todos los fallos y alertar ante patrones de ataque.

MFA correctamente implementado

  • Priorizar MFA resistente a phishing: passkeys basadas en WebAuthn / FIDO2. Vinculan la credencial al dominio del verificador (origin binding), por lo que no pueden ser capturadas por sitios de phishing ni reutilizadas como un OTP. Es la recomendación actual de FIDO Alliance y de NIST SP 800-63B.
  • Considerar OTP por SMS o email como un escalón mínimo y de transición, no como objetivo: el SMS es vulnerable a interceptación y SIM swapping. Una app TOTP es preferible al SMS, pero por debajo de las passkeys.
  • Verificar el segundo factor antes de crear o validar la sesión definitiva.
  • Aplicar rate limiting también a los intentos de código TOTP.
  • No permitir que el flujo de recuperación de cuenta anule el MFA sin verificación adicional.

Mensajes de error neutros

  • Usar siempre el mismo mensaje genérico para credenciales incorrectas: «Usuario o contraseña incorrectos». Nunca distinguir si el usuario existe o no.
  • Normalizar los tiempos de respuesta para que el servidor tarde lo mismo si el usuario existe o no (calcular el hash aunque el usuario no exista, para igualar el tiempo).

Cookies de sesión seguras

Set-Cookie: sessionId=<valor>; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age=1800
  • HttpOnly: impide acceso desde JavaScript (mitiga XSS → robo de cookie).
  • Secure: solo se envía por HTTPS.
  • SameSite=Strict: no se envía en peticiones cruzadas (mitiga CSRF).
  • Max-Age: expiración razonable (1800 segundos = 30 minutos de inactividad).

Rotación de sesión al autenticar

La defensa principal contra la fijación de sesión es regenerar siempre el ID de sesión tras un login exitoso. En PHP: session_regenerate_id(true). En Express/Node: destruir la sesión anterior y crear una nueva tras autenticar. En Django, esto ocurre automáticamente con login(request, user).

JWT seguros

  • Usar algoritmos asimétricos (RS256, ES256) en lugar de HS256 cuando sea posible.
  • Si usas HS256, generar el secreto con un CSPRNG y una longitud de al menos 256 bits.
  • Rechazar explícitamente alg:none en la configuración de la librería. Verificar que la librería no acepta tokens sin firma.
  • Fijar en el servidor el algoritmo esperado y no permitir que el header alg del token decida cómo se verifica la firma: así se previene la confusión de algoritmo (RS256↔HS256).
  • Incluir siempre la claim exp (expiración) y validarla.
  • Para revocación de tokens, mantener una lista negra de JTI (JWT ID) en Redis u otra caché.

Ejercicio propuesto

Combina lo aprendido en este módulo completando el siguiente flujo de ataque y defensa en tu laboratorio personal:

  1. Reconocimiento: en tu instancia de Juice Shop, identifica todos los endpoints de autenticación (/api/Users/login, rutas de recuperación de contraseña).
  2. Enumeración: usa Burp Intruder para identificar al menos dos usuarios válidos mediante diferencias en los mensajes de respuesta o tiempos.
  3. Explotación: realiza fuerza bruta del usuario encontrado con una wordlist de 20 contraseñas comunes. Documenta el número de peticiones necesarias y el tiempo empleado.
  4. Análisis de JWT: inspecciona el token devuelto en jwt.io. Identifica el algoritmo, las claims presentes y si hay campo de expiración.
  5. Defensa: en una copia local del código (o en un proyecto Express/Flask de prueba), implementa rate limiting en el endpoint de login y verifica que los intentos quedan bloqueados tras 5 fallos.
  6. Entrega: escribe un informe de una página con capturas de Burp, las vulnerabilidades encontradas y las medidas correctoras aplicadas. Usa el formato de informe de pentest descrito en la guía completa de hacking web.

Errores comunes

  • Confundir cifrado con hashing: las contraseñas se hashean (proceso irreversible), no se cifran. Si «descifras» una contraseña, es que se almacenó cifrada (mal) o en texto plano (peor).
  • Invalidar la cookie pero no la sesión del servidor: borrar la cookie en el navegador no destruye la sesión si el backend no la invalida. El token capturado previamente sigue siendo válido.
  • Implementar MFA pero no protegerlo contra fuerza bruta: el segundo factor de 6 dígitos es solo tan seguro como la limitación de intentos que lo rodea.
  • Usar el mismo secreto JWT en todos los entornos: desarrollo, staging y producción deben tener secretos independientes y nunca compartidos en repositorios.
  • Confiar en el payload del JWT sin verificar la firma: el payload está solo en Base64, no cifrado. Siempre verificar la firma antes de leer cualquier claim.
  • Rate limiting solo por IP: un atacante con una botnet o a través de Tor puede rotar IPs. Combinar con rate limiting por cuenta de usuario y CAPTCHAs adaptativos.

Preguntas frecuentes

¿Qué diferencia hay entre autenticación y autorización?

Autenticación es verificar quién eres (login, tokens). Autorización es verificar qué tienes permitido hacer una vez que ya se sabe quién eres (permisos, roles, ACLs). Son capas independientes y los fallos en cada una producen vulnerabilidades distintas. OWASP A07:2025 (Authentication Failures) trata la autenticación; los fallos de control de acceso son otra categoría del Top 10 (A01:2025, Broken Access Control).

¿Los JWT son seguros por defecto?

No por defecto, sino por implementación. La especificación JWT es amplia y permite configuraciones inseguras como alg:none. La seguridad depende de: elegir el algoritmo correcto, usar secretos o claves de suficiente longitud y entropía, validar todas las claims relevantes (exp, iss, aud), y usar una librería actualizada que rechace configuraciones peligrosas. Bibliotecas como python-jose, jsonwebtoken (Node) o java-jwt tienen configuraciones seguras, pero deben usarse correctamente.

¿Cómo sé si una app en producción es vulnerable a enumeración de usuarios?

De forma ética y legal solo en aplicaciones sobre las que tengas autorización escrita. El método es comparar las respuestas del formulario de login ante un usuario que sabes que no existe (inventa uno) y un usuario que sabes que sí existe (el tuyo propio). Si el mensaje de error, el código HTTP o el tiempo de respuesta difieren, la enumeración es posible. Para análisis más precisos de timing, usa herramientas con control de latencia como Burp Suite o scripts Python con medición de time.perf_counter().

¿Qué pasa si no tengo MFA disponible para implementar en mi proyecto?

La opción más recomendable hoy son las passkeys (WebAuthn / FIDO2), resistentes a phishing y soportadas de forma nativa por los navegadores y sistemas operativos modernos; bibliotecas como SimpleWebAuthn (Node) o py_webauthn (Python) las integran en un proyecto propio. Como alternativa o complemento, los TOTP (Time-based One-Time Password) son gratuitos y de código abierto: librerías como pyotp (Python), speakeasy (Node.js) o BaconQrCode (PHP) permiten integrarlos en horas, y son compatibles con Google Authenticator y Authy (estándar RFC 6238). Para proyectos mayores, considera proveedores de identidad como Auth0, Cognito o Keycloak, que incluyen MFA y passkeys out-of-the-box. La integración de MFA es hoy uno de los controles con mejor relación coste-seguridad disponible.

Recursos y siguientes pasos

Este módulo cubre los fundamentos de autenticación y sesiones. Para profundizar, los siguientes recursos oficiales son el punto de partida:

Recordatorio legal y ético final: Las técnicas descritas en este módulo — fuerza bruta, enumeración de usuarios, manipulación de sesiones y análisis de JWT — son ilegales cuando se aplican contra sistemas sin autorización explícita del propietario. En España, el artículo 197 bis del Código Penal tipifica el acceso no autorizado a sistemas informáticos con penas de hasta dos años de prisión. Practica siempre en entornos controlados: Juice Shop, DVWA, PortSwigger Web Security Academy o tus propias máquinas virtuales. El conocimiento de los ataques tiene un único propósito válido: construir sistemas más seguros.