El OWASP Top 10 es el estándar más reconocido para la seguridad de aplicaciones web. Si sos desarrollador, conocer estas 10 categorías de vulnerabilidades no es opcional: es parte de tu responsabilidad profesional.

En esta guía práctica, vamos a ver cada categoría con ejemplos concretos de código y cómo prevenir cada vulnerabilidad.

A01:2021 — Control de Acceso Roto

El control de acceso roto es la vulnerabilidad más común. Ocurre cuando un usuario puede acceder a datos o funcionalidades que no debería.

Ejemplo vulnerable (Node.js/Express)

// ❌ MAL: No se verifica que el usuario sea dueño del recurso
app.get('/api/usuarios/:id', (req, res) => {
  const usuario = db.usuarios.findById(req.params.id);
  res.json(usuario);
});

Cómo prevenirlo

// ✅ BIEN: Verificar ownership
app.get('/api/usuarios/:id', auth, (req, res) => {
  const usuario = db.usuarios.findById(req.params.id);
  if (usuario.empresaId !== req.user.empresaId) {
    return res.status(403).json({ error: 'No autorizado' });
  }
  res.json(usuario);
});

A02:2021 — Fallas Criptográficas

Ocurren cuando los datos sensibles no están adecuadamente protegidos.

Ejemplo vulnerable

// ❌ MAL: Contraseñas en texto plano
const usuario = {
  email: req.body.email,
  password: req.body.password // ¡NUNCA guardar en texto plano!
};
db.usuarios.insert(usuario);

Cómo prevenirlo

// ✅ BIEN: Usar bcrypt con salt
const bcrypt = require('bcrypt');
const saltRounds = 12;
const hash = await bcrypt.hash(req.body.password, saltRounds);
const usuario = { email: req.body.email, password: hash };

A03:2021 — Inyección

La más famosa es SQL Injection, pero también hay inyección de comandos, LDAP, NoSQL y más.

Ejemplo vulnerable (SQL Injection)

# ❌ MAL: Concatenar strings en queries SQL
query = f"SELECT * FROM usuarios WHERE email = '{email}' AND password = '{password}'"
cursor.execute(query)

Un atacante podría ingresar admin@empresa.com' -- como email y el password sería ignorado.

Cómo prevenirlo

# ✅ BIEN: Usar parametrized queries
cursor.execute(
    "SELECT * FROM usuarios WHERE email = %s AND password = %s",
    (email, password)
)

Estos son solo los primeros tres del Top 10. En próximos artículos cubriremos el resto de las categorías. Mientras tanto, recordá: nunca confíes en el input del usuario, siempre validá, siempre sanitizá, y nunca construyas queries concatenando strings.