Principiante
CVSS 8.1 - Alto
19 min
Broken Authentication
Implementaciones débiles de autenticación y gestión de sesiones
¿Qué es Broken Authentication?
Implementación incorrecta de autenticación que permite a atacantes comprometer contraseñas, tokens, o explotar fallas de implementación para asumir la identidad de otros usuarios.
Vulnerabilidades Comunes
- • Permitir ataques de fuerza bruta sin rate limiting
- • Contraseñas débiles o predeterminadas
- • Almacenar contraseñas en texto plano o con hash débil
- • Session fixation
- • Tokens predecibles o sin expiración
- • Falta de autenticación multi-factor
Ejemplos de Vulnerabilidades
1. Sin Rate Limiting
// ❌ VULNERABLE
app.post('/login', async (req, res) => {
const { username, password } = req.body;
const user = await db.users.findOne({ username });
if (!user || !await bcrypt.compare(password, user.passwordHash)) {
return res.status(401).json({ error: 'Invalid credentials' });
}
res.json({ token: generateToken(user) });
});
// Atacante puede probar millones de contraseñas2. Session Fixation
// ❌ VULNERABLE - no regenerar session ID después del login
app.post('/login', (req, res) => {
// Autenticar usuario...
req.session.userId = user.id; // Usar mismo session ID
res.json({ success: true });
});
// ✅ SEGURO - regenerar session
app.post('/login', (req, res) => {
req.session.regenerate((err) => {
req.session.userId = user.id;
res.json({ success: true });
});
});3. Contraseñas Débiles
// ❌ VULNERABLE - sin validación de complejidad
app.post('/register', async (req, res) => {
const { password } = req.body;
const hash = await bcrypt.hash(password, 10);
// Acepta "123" como contraseña
});
// ✅ SEGURO - validar complejidad
const passwordSchema = Joi.string()
.min(12)
.pattern(/[a-z]/) // lowercase
.pattern(/[A-Z]/) // uppercase
.pattern(/[0-9]/) // number
.pattern(/[^a-zA-Z0-9]/) // special char
.required();Mejores Prácticas
// 1. Rate Limiting
const rateLimit = require('express-rate-limit');
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5,
message: 'Demasiados intentos'
});
app.post('/login', loginLimiter, loginHandler);
// 2. Password Hashing (bcrypt)
const bcrypt = require('bcrypt');
const saltRounds = 12;
const hash = await bcrypt.hash(password, saltRounds);
// 3. Multi-Factor Authentication
const speakeasy = require('speakeasy');
const verified = speakeasy.totp.verify({
secret: user.twoFactorSecret,
encoding: 'base32',
token: req.body.totpCode
});
// 4. Secure Session Management
app.use(session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 3600000 // 1 hora
}
}));
// 5. Account Lockout
let failedAttempts = 0;
if (failedAttempts >= 5) {
await db.users.update(userId, {
lockedUntil: new Date(Date.now() + 15*60*1000)
});
}