Enumeración de Usuarios por Mensajes de Error Distintos
Endpoints de login o reset de contraseña que devuelven mensajes de error diferentes para 'email no encontrado' vs 'contraseña incorrecta', permitiendo a atacantes confirmar qué direcciones de email están registradas.
Cómo Funciona
Si tu login dice 'No se encontró cuenta con este email' para usuarios desconocidos e 'Contraseña incorrecta' para usuarios conocidos, los atacantes pueden recorrer listas de emails para descubrir cuáles están registrados. Esto impulsa phishing dirigido, credential stuffing y saber a quién perseguir. Un único mensaje cubre ambos casos.
// MAL: mensajes diferentes revelan existencia de cuenta
if (!user) return Response.json({ error: 'No hay cuenta con este email' }, { status: 401 });
if (!await bcrypt.compare(password, user.passwordHash)) {
return Response.json({ error: 'Contraseña incorrecta' }, { status: 401 });
}// BIEN: mismo mensaje independientemente de cuál check falló
if (!user || !await bcrypt.compare(password, user.passwordHash)) {
return Response.json({ error: 'Email o contraseña inválidos' }, { status: 401 });
}Ejemplo Real
Los flujos de reset de contraseña son especialmente propensos a esto: 'Te enviamos un email de reset' vs 'No hay cuenta con ese email' le dice exactamente a los atacantes quién está registrado. Muchas plataformas importantes recibieron reportes de bounty por esto, incluyendo LinkedIn y Twitter.
Cómo Prevenirlo
- Usa el mismo mensaje de error para los casos 'usuario no encontrado' y 'contraseña incorrecta'
- Para reset de contraseña, siempre di 'Si ese email está registrado, recibirás un link' — independientemente
- Aplica el mismo retardo de respuesta independientemente de si el usuario existe (previene ataques de timing)
- Limita la tasa de intentos de enumeración por IP
Tecnologías Afectadas
Data Hogo detecta esta vulnerabilidad automáticamente.
Escanea Tu Repo GratisVulnerabilidades Relacionadas
Fijación de Sesión
highEl servidor reutiliza el mismo ID de sesión antes y después del login, permitiendo a un atacante que plantó un ID de sesión conocido secuestrar la sesión autenticada.
Sin Bloqueo de Cuenta / Protección contra Fuerza Bruta
mediumEndpoints de login sin rate limiting ni mecanismo de bloqueo, permitiendo a atacantes probar combinaciones ilimitadas de usuario y contraseña hasta encontrar credenciales válidas.
Política de Contraseña Débil
mediumSin requisitos de longitud mínima, complejidad o verificación contra contraseñas comunes en el registro o cambio de contraseña, haciendo las cuentas fácilmente vulnerables a fuerza bruta.
OAuth Sin Parámetro State
highFlujo de autorización OAuth implementado sin un parámetro `state` aleatorio, permitiendo ataques CSRF que vinculan la cuenta de una víctima con la identidad OAuth del atacante.