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.