Seguridad Web en 2026: Guía Práctica del OWASP Top 10 para Desarrolladores
Las 10 vulnerabilidades más críticas en aplicaciones web según OWASP y cómo prevenirlas con ejemplos de código reales. Protege tu aplicación desde el primer commit.
La seguridad no es un feature — es un requisito. Sin embargo, la mayoría de los equipos de desarrollo la tratan como un paso final, algo que se revisa “antes de salir a producción”. El resultado: el 91% de las aplicaciones web tienen al menos una vulnerabilidad crítica según el último reporte de OWASP.
En CloudLabs, la seguridad es parte del proceso desde el diseño. Esta guía cubre las 10 vulnerabilidades más comunes según OWASP 2025 con ejemplos prácticos y soluciones que puedes implementar hoy.
1. Broken Access Control (Control de Acceso Roto)
La vulnerabilidad #1. Ocurre cuando un usuario puede acceder a recursos o realizar acciones que no debería.
Ejemplo vulnerable:
// ❌ Cualquier usuario autenticado puede ver cualquier pedido
app.get('/api/orders/:id', authenticate, async (req, res) => {
const order = await Order.findById(req.params.id);
res.json(order);
});
Solución:
// ✅ Verificar que el pedido pertenece al usuario
app.get('/api/orders/:id', authenticate, async (req, res) => {
const order = await Order.findOne({
_id: req.params.id,
userId: req.user.id // Solo sus propios pedidos
});
if (!order) return res.status(404).json({ error: 'Not found' });
res.json(order);
});
Regla de oro: nunca confíes solo en la autenticación. Siempre verifica autorización a nivel de recurso.
2. Cryptographic Failures (Fallos Criptográficos)
Datos sensibles expuestos o mal cifrados: contraseñas en texto plano, tokens predecibles, comunicaciones sin TLS.
Checklist mínimo:
- Contraseñas hasheadas con bcrypt o argon2 (nunca MD5 o SHA-1)
- HTTPS obligatorio en toda la aplicación
- Tokens JWT firmados con algoritmos seguros (RS256, ES256)
- Variables de entorno para secretos, nunca hardcodeados
- Datos sensibles cifrados en reposo (AES-256-GCM)
// ✅ Hashear contraseñas correctamente
import bcrypt from 'bcryptjs';
const hash = await bcrypt.hash(password, 12);
const isValid = await bcrypt.compare(inputPassword, hash);
3. Injection (Inyección)
SQL injection, NoSQL injection, command injection. Sigue siendo una de las vulnerabilidades más explotadas.
// ❌ SQL Injection vulnerable
const query = `SELECT * FROM users WHERE email = '${email}'`;
// ✅ Queries parametrizados
const result = await db.query(
'SELECT * FROM users WHERE email = $1',
[email]
);
Para ORMs modernos, la mayoría maneja esto automáticamente, pero cuidado con raw queries y operadores dinámicos en MongoDB/Mongoose.
4. Insecure Design (Diseño Inseguro)
No es un bug de implementación — es un problema de arquitectura. Ejemplos:
- API de recuperación de contraseña que revela si un email existe
- Sin rate limiting en endpoints de autenticación
- Lógica de negocio que permite manipulación de precios desde el frontend
Solución: incluir threat modeling en la fase de diseño. Preguntar “¿qué pasa si un usuario malintencionado hace X?” antes de escribir código.
5. Security Misconfiguration
Configuraciones por defecto que nunca se cambiaron:
// ✅ Headers de seguridad con Helmet.js
import helmet from 'helmet';
app.use(helmet());
// ✅ CORS restrictivo
app.use(cors({
origin: ['https://tudominio.com'],
credentials: true
}));
// ✅ Deshabilitar headers que revelan tecnología
app.disable('x-powered-by');
También aplica a: permisos de cloud (S3 buckets públicos), puertos abiertos, credenciales por defecto en bases de datos.
6. Vulnerable and Outdated Components
El 77% de las aplicaciones usan al menos un componente con vulnerabilidades conocidas.
# Auditar dependencias regularmente
npm audit
pip audit
snyk test
# Automatizar con Dependabot o Renovate Bot
Tip: configura alertas automáticas de seguridad en GitHub y revisa el npm audit en tu pipeline de CI.
7. Authentication Failures
Contraseñas débiles permitidas, falta de MFA, tokens que no expiran.
Implementación segura:
// ✅ Configuración robusta de sesión
app.use(session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {
secure: true, // Solo HTTPS
httpOnly: true, // No accesible desde JS
sameSite: 'strict', // Previene CSRF
maxAge: 3600000 // 1 hora
}
}));
8. Software and Data Integrity Failures
CI/CD pipelines sin verificación, dependencias de fuentes no confiables, updates sin firma.
Protecciones:
- Usar
package-lock.json/pnpm-lock.yamly verificar integridad - Firmar commits con GPG
- Proteger branches principales con reglas de protección
- Verificar checksums de dependencias descargadas
9. Security Logging and Monitoring Failures
Si no puedes detectar un ataque, no puedes responder a tiempo.
Mínimo viable de logging:
// ✅ Loggear intentos de autenticación fallidos
logger.warn('Failed login attempt', {
email: sanitize(email),
ip: req.ip,
timestamp: new Date().toISOString(),
userAgent: req.headers['user-agent']
});
Combina con herramientas como Sentry, Datadog o ELK Stack para alertas en tiempo real.
10. Server-Side Request Forgery (SSRF)
Cuando tu servidor hace requests a URLs controladas por el usuario sin validación.
// ❌ SSRF vulnerable
app.post('/api/fetch-url', async (req, res) => {
const response = await fetch(req.body.url);
res.json(await response.json());
});
// ✅ Validar y restringir URLs permitidas
const ALLOWED_HOSTS = ['api.example.com', 'cdn.example.com'];
app.post('/api/fetch-url', async (req, res) => {
const url = new URL(req.body.url);
if (!ALLOWED_HOSTS.includes(url.hostname)) {
return res.status(403).json({ error: 'Host not allowed' });
}
const response = await fetch(url.toString());
res.json(await response.json());
});
Checklist de seguridad para cada deploy
- ✅ Headers de seguridad configurados (Helmet.js o equivalente)
- ✅ HTTPS forzado, HSTS habilitado
- ✅ Inputs validados y sanitizados en servidor
- ✅ Queries parametrizados (sin concatenación de strings)
- ✅ Rate limiting en endpoints sensibles
- ✅ CORS configurado correctamente
- ✅ Dependencias auditadas sin CVEs críticos
- ✅ Secretos en variables de entorno, nunca en código
- ✅ Logging de eventos de seguridad activo
- ✅ Autenticación con MFA disponible
La seguridad es un proceso, no un destino
No existe el software 100% seguro. Pero la diferencia entre una aplicación vulnerable y una resiliente está en cuánto consideras la seguridad desde el primer día. En CloudLabs, cada proyecto incluye revisión de seguridad como parte del flujo de desarrollo, no como un paso extra al final.
Si necesitas una auditoría de seguridad o quieres que tu próximo proyecto nazca seguro desde el diseño, conversemos.
¿Te interesa este tema?
En CloudLabs implementamos estas soluciones para empresas reales. Conversemos sobre tu proyecto.
Hablemos →Hans Vergara
Lead Developer & Founder en CloudLabs