Wiki/Vulnerabilidades/Broken Authentication
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ñas

2. 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)
  });
}

Siguiente Paso

Aprende sobre defensas y mitigaciones

Ir a Defensas