Seguridad Web: OWASP Top 10 y Cómo Protegerte
24 de diciembre de 2025
Osman Jimenez
Seguridad OWASP Desarrollo Web
Protegiendo Aplicaciones Web
La seguridad es crítica. Aprende las vulnerabilidades más comunes según OWASP y cómo proteger tus aplicaciones.
1. Broken Access Control
// ❌ Vulnerable
app.get('/api/users/:id', (req, res) => {
const user = await User.findById(req.params.id);
res.json(user);
});
// ✅ Seguro
app.get('/api/users/:id', authenticate, (req, res) => {
if (req.user.id !== req.params.id && !req.user.isAdmin) {
return res.status(403).json({ error: 'Forbidden' });
}
const user = await User.findById(req.params.id);
res.json(user);
});2. Cryptographic Failures
// ❌ Nunca guardes passwords en texto plano
const user = { password: 'password123' };
// ✅ Usa bcrypt
import bcrypt from 'bcrypt';
const hashedPassword = await bcrypt.hash(password, 10);
const isValid = await bcrypt.compare(password, hashedPassword);
// ✅ Usa HTTPS siempre
// ✅ Encripta datos sensibles en BD3. Injection (SQL, NoSQL, Command)
// ❌ SQL Injection vulnerable
const query = `SELECT * FROM users WHERE email = '${email}'`;
// ✅ Usa prepared statements
const query = 'SELECT * FROM users WHERE email = ?';
const users = await db.query(query, [email]);
// ❌ NoSQL Injection
User.find({ email: req.body.email });
// ✅ Valida y sanitiza
const email = validator.isEmail(req.body.email) ? req.body.email : null;
if (!email) return res.status(400).json({ error: 'Invalid email' });4. Insecure Design
// Implementa rate limiting
import rateLimit from 'express-rate-limit';
const limiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100
});
app.use('/api/', limiter);
// Implementa CAPTCHA para acciones sensibles
// Usa 2FA para autenticación5. Security Misconfiguration
// ❌ Exponer información sensible
app.use((err, req, res, next) => {
res.status(500).json({ error: err.stack });
});
// ✅ Ocultar detalles en producción
app.use((err, req, res, next) => {
console.error(err);
res.status(500).json({
error: process.env.NODE_ENV === 'production'
? 'Internal Server Error'
: err.message
});
});
// Configurar headers de seguridad
import helmet from 'helmet';
app.use(helmet());6. Vulnerable Components
# Auditar dependencias
npm audit
npm audit fix
# Usar Snyk o Dependabot
# Mantener dependencias actualizadas
npm outdated
npm update7. Authentication Failures
// Implementar JWT correctamente
import jwt from 'jsonwebtoken';
const token = jwt.sign(
{ userId: user.id },
process.env.JWT_SECRET,
{ expiresIn: '1h' }
);
// Validar tokens
const authenticate = (req, res, next) => {
const token = req.headers.authorization?.split(' ')[1];
if (!token) {
return res.status(401).json({ error: 'No token' });
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
next();
} catch (error) {
res.status(401).json({ error: 'Invalid token' });
}
};8. Software and Data Integrity Failures
// Verificar integridad de archivos subidos
import crypto from 'crypto';
function verifyChecksum(file, expectedHash) {
const hash = crypto.createHash('sha256');
hash.update(file);
return hash.digest('hex') === expectedHash;
}
// Usar Subresource Integrity (SRI)
9. Logging and Monitoring Failures
// Implementar logging adecuado
import winston from 'winston';
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
]
});
// Log eventos de seguridad
logger.warn('Failed login attempt', {
email,
ip: req.ip,
timestamp: new Date()
});10. Server-Side Request Forgery (SSRF)
// ❌ Vulnerable
app.get('/fetch', async (req, res) => {
const url = req.query.url;
const response = await fetch(url);
res.send(await response.text());
});
// ✅ Validar URLs
const allowedDomains = ['api.example.com'];
app.get('/fetch', async (req, res) => {
const url = new URL(req.query.url);
if (!allowedDomains.includes(url.hostname)) {
return res.status(400).json({ error: 'Invalid domain' });
}
const response = await fetch(url.toString());
res.send(await response.text());
});XSS Prevention
// Sanitizar input
import DOMPurify from 'isomorphic-dompurify';
const clean = DOMPurify.sanitize(dirtyHTML);
// Content Security Policy
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'"],
styleSrc: ["'self'", "'unsafe-inline'"]
}
}));CSRF Protection
import csrf from 'csurf';
const csrfProtection = csrf({ cookie: true });
app.get('/form', csrfProtection, (req, res) => {
res.render('form', { csrfToken: req.csrfToken() });
});
app.post('/process', csrfProtection, (req, res) => {
// Procesar formulario
});CORS Seguro
import cors from 'cors';
const corsOptions = {
origin: ['https://example.com'],
credentials: true,
optionsSuccessStatus: 200
};
app.use(cors(corsOptions));Checklist de Seguridad
- ✅ HTTPS en producción
- ✅ Validar y sanitizar inputs
- ✅ Usar prepared statements
- ✅ Hash passwords con bcrypt
- ✅ Implementar rate limiting
- ✅ Configurar headers de seguridad
- ✅ Mantener dependencias actualizadas
- ✅ Implementar logging
- ✅ Usar JWT correctamente
- ✅ Proteger contra XSS y CSRF
Conclusión
La seguridad no es opcional. Implementa estas prácticas desde el inicio y mantente actualizado con las últimas vulnerabilidades y parches.