Backend
Backend - Seguridad Básica
Conceptos fundamentales de seguridad para desarrolladores backend: OWASP, SQL Injection, autenticación JWT, rate limiting y validación de inputs
ScreeningConceptosBest Practices
Introducción
La seguridad es fundamental en el desarrollo backend. Estos son los conceptos básicos que todo desarrollador debe conocer para proteger sus aplicaciones.
OWASP Top 10
1 preguntas
1
¿Qué es OWASP Top 10?
Resumen: Lista de los 10 riesgos de seguridad más críticos en aplicaciones web.
OWASP Top 10 (2021):
1.A01: Broken Access Control - Controles de acceso rotos
2.A02: Cryptographic Failures - Fallos criptográficos
3.A03: Injection - Inyección (SQL, NoSQL, etc.)
4.A04: Insecure Design - Diseño inseguro
5.A05: Security Misconfiguration - Configuración insegura
6.A06: Vulnerable Components - Componentes vulnerables
7.A07: Authentication Failures - Fallos de autenticación
8.A08: Software and Data Integrity - Integridad de software y datos
9.A09: Security Logging Failures - Fallos en logging de seguridad
10.A10: Server-Side Request Forgery - SSRF
Importancia:
✓Guía estándar de la industria
✓Actualizada regularmente
✓Base para auditorías de seguridad
✓Prioriza riesgos más comunes
SQL Injection
2 preguntas
1
¿Qué es SQL Injection y cómo prevenirla?
Definición: Ataque que inserta código SQL malicioso en consultas de base de datos.
Ejemplo vulnerable:
javascript
// ❌ VULNERABLE
const query = `SELECT * FROM users WHERE username = '${username}'`;Ejemplo seguro:
javascript
// ✅ SEGURO - Prepared Statements
const query = 'SELECT * FROM users WHERE username = ?';
db.query(query, [username]);Prevención:
✓Prepared Statements / Parameterized Queries - Siempre usar
✓ORM - Usar ORMs que escapen automáticamente
✓Validación de inputs - Validar y sanitizar datos
✓Principio de menor privilegio - DB user con permisos mínimos
✓WAF - Web Application Firewall como capa adicional
Tipos comunes:
•Union-based:
' UNION SELECT * FROM users--•Error-based: Explota mensajes de error
•Blind: Sin feedback directo
•Time-based: Usa delays para extraer datos
2
¿Cómo funciona SQL Injection en diferentes bases de datos?
SQL Injection no solo afecta a SQL:
| Base de Datos | Tipo | Ejemplo | Prevención |
|---|---|---|---|
MySQL/PostgreSQL | SQL | ' OR '1'='1 | Prepared statements |
MongoDB | NoSQL | {"$gt": ""} | Validación estricta |
Redis | Key-Value | Comandos maliciosos | Sanitización |
NoSQL Injection ejemplo:
javascript
// ❌ VULNERABLE
const user = db.users.findOne({ username: req.body.username });
// Si username = {"$gt": ""} puede retornar todos los usuarios
// ✅ SEGURO
const username = String(req.body.username); // Validar tipo
const user = db.users.findOne({ username: username });Mejores prácticas:
•Validar tipos de datos
•Usar librerías oficiales
•Escapar caracteres especiales
•Limitar operadores permitidos
Autenticación y JWT
2 preguntas
1
¿Cómo funciona JWT (JSON Web Token)?
Estructura:
header.payload.signatureComponentes:
1.Header: Tipo de token y algoritmo
json
{"alg": "HS256", "typ": "JWT"}2.Payload: Datos (claims)
json
{"sub": "123", "name": "Juan", "exp": 1234567890}3.Signature: Verificación
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)Flujo:
1.Usuario se autentica → Server genera JWT
2.Client guarda token (localStorage/cookie)
3.Client envía token en headers:
Authorization: Bearer <token>4.Server valida signature y expiración
Ventajas:
✓Stateless (no necesita sesión en servidor)
✓Escalable
✓Portable entre dominios
Desventajas:
✗ No se puede revocar fácilmente (necesita blacklist)
✗ Tamaño mayor que session ID
✗ Payload es decodificable (no encriptado, solo firmado)
2
¿Cuáles son las mejores prácticas para JWT?
Seguridad:
✓Almacenamiento seguro:
• HttpOnly cookies (mejor que localStorage)
• SameSite attribute
• Secure flag en HTTPS
✓Expiración corta:
• Access token: 15-60 minutos
• Refresh token: 7-30 días
✓Refresh Token Pattern:
javascript
// Access token corto + Refresh token largo
{
accessToken: "eyJ...", // 15 min
refreshToken: "eyJ..." // 7 días
}✓Validación:
• Verificar signature
• Verificar expiración (exp)
• Verificar issuer (iss)
• Verificar audience (aud)
✓No poner datos sensibles:
• El payload es decodificable
• Solo información necesaria
✓HTTPS siempre:
• JWT debe viajar solo por HTTPS
Implementación:
•Usar librerías probadas (jsonwebtoken, jose)
•Rotar secretos regularmente
•Implementar blacklist para logout
Rate Limiting
2 preguntas
1
¿Qué es Rate Limiting y por qué es importante?
Definición: Limitar el número de solicitudes que un cliente puede hacer en un período de tiempo.
Propósito:
✓Prevenir abuso y ataques DDoS
✓Proteger recursos del servidor
✓Prevenir scraping
✓Asegurar uso justo del servicio
Estrategias comunes:
| Estrategia | Descripción | Uso |
|---|---|---|
Fixed Window | Contador por ventana fija | Simple, puede tener spikes |
Sliding Window | Ventana deslizante | Más preciso |
Token Bucket | Tokens que se consumen | Flexible, permite bursts |
Leaky Bucket | Rate constante | Suaviza tráfico |
Ejemplo:
javascript
// 100 requests por 15 minutos por IP
rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutos
max: 100, // máximo 100 requests
keyGenerator: (req) => req.ip
});Headers de respuesta:
•
X-RateLimit-Limit: Límite total•
X-RateLimit-Remaining: Requests restantes•
X-RateLimit-Reset: Tiempo de reset2
¿Cómo implementar Rate Limiting?
Implementación con Redis:
javascript
// Usando Redis para almacenar contadores
async function rateLimit(ip, limit = 100, window = 15 * 60) {
const key = `rate_limit:${ip}`;
const current = await redis.incr(key);
if (current === 1) {
await redis.expire(key, window);
}
if (current > limit) {
return { allowed: false, remaining: 0 };
}
return { allowed: true, remaining: limit - current };
}Middleware ejemplo (Express):
javascript
app.use('/api/', rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
message: 'Too many requests'
}));Diferentes límites por endpoint:
•Login: 5 intentos por hora
•API pública: 100 requests/minuto
•API autenticada: 1000 requests/minuto
•Upload: 10 archivos/hora
Mejores prácticas:
✓Diferentes límites por tipo de usuario
✓Límites más estrictos en endpoints sensibles
✓Logging de intentos bloqueados
✓Mensajes de error claros
✓Considerar IP + User ID combinados
Validación de Inputs
2 preguntas
1
¿Por qué es importante validar inputs y cómo hacerlo?
Razones:
✓Prevenir inyección (SQL, XSS, Command)
✓Asegurar integridad de datos
✓Mejorar UX con errores claros
✓Cumplir con reglas de negocio
Validación en múltiples capas:
1.Frontend (UX):
• Validación inmediata
• Feedback visual
• No confiable para seguridad
2.Backend (Seguridad):
• Validación obligatoria
• Única fuente de verdad
• Sanitización de datos
Tipos de validación:
| Tipo | Ejemplo | Validación |
|---|---|---|
Tipo | String, Number, Boolean | typeof input === 'string' |
Formato | Email, URL, Phone | Regex, validadores |
Rango | Min/Max length, valores | input.length >= 5 && input.length <= 50 |
Contenido | Sin caracteres peligrosos | Whitelist de caracteres |
Reglas de negocio | Unicidad, formato específico | Lógica custom |
Ejemplo con librería (Joi/Zod):
javascript
const schema = Joi.object({
email: Joi.string().email().required(),
age: Joi.number().integer().min(18).max(120),
password: Joi.string().min(8).pattern(/[A-Z]/).required()
});
const { error, value } = schema.validate(req.body);2
¿Cuál es la diferencia entre validación y sanitización?
Validación: Verifica que los datos cumplan reglas → Acepta o rechaza
Sanitización: Limpia/modifica datos → Acepta datos modificados
Ejemplos:
Validación:
javascript
// ❌ Rechaza si no cumple
if (!email.includes('@')) {
throw new Error('Invalid email');
}Sanitización:
javascript
// ✅ Limpia y acepta
const cleanEmail = email.trim().toLowerCase();
const cleanHtml = DOMPurify.sanitize(userInput);Cuándo usar cada una:
| Escenario | Validación | Sanitización |
|---|---|---|
Email | ✅ Formato correcto | Trim, lowercase |
HTML | ❌ No permitir | ✅ Limpiar tags peligrosos |
SQL | ❌ No permitir | ✅ Usar prepared statements |
Números | ✅ Tipo y rango | Parse a número |
Regla general:
•Validar datos que deben cumplir reglas estrictas
•Sanitizar cuando necesitas limpiar pero aceptar
•Rechazar datos peligrosos en lugar de sanitizar
•Nunca confiar en sanitización para seguridad crítica