Ya sabemos qué es el ASVS y que BazarNube apunta al Nivel 2. Toca abrir el catálogo y trabajar con los requisitos reales. En esta lección recorreremos los capítulos de requisitos más relevantes para una aplicación web como BazarNube, aprenderemos a leer un requisito verificable con precisión y —lo más útil de todo— mapearemos los hallazgos del Top Ten del módulo 3 a requisitos ASVS concretos. Ese mapeo es el que convierte el backlog disperso de BazarNube en una checklist verificable y ordenada por capítulos.
Contenido
- Cómo leer un requisito verificable
- V2 – Autenticación
- V3 – Gestión de sesiones
- V4 – Control de acceso
- V5 – Validación, sanitización y codificación
- V6 – Criptografía almacenada
- V7 – Manejo de errores y logging
- V8/V9 – Protección de datos y comunicaciones
- V14 – Configuración
- Mapa: hallazgos Top Ten de BazarNube → requisitos ASVS
Cómo leer un requisito verificable
Antes de recorrer capítulos, fijemos el método de lectura. Un requisito ASVS se lee identificando cuatro cosas:
V5.3.3 "Verificar que la codificacion de salida sensible al contexto
se realiza cerca o por el interprete al que va destinada."
Niveles: L1 L2 L3 CWE-116
1. QUE afirma -> "se hace codificacion de salida por contexto"
2. COMO se comprueba -> revisar el codigo de renderizado/plantillas
3. EN QUE NIVEL aplica -> L1, L2 y L3 (obligatorio ya desde L1)
4. QUE debilidad cubre -> CWE-116 (codificacion incorrecta de salida)Regla práctica: si no puedes responder "cumple / no cumple / no aplica" tras leerlo, no lo has terminado de verificar. Cada requisito es un caso de prueba, no una recomendación. Con ese método, recorramos los capítulos clave.
V2 – Autenticación
Reúne los requisitos sobre credenciales, su ciclo de vida y protección frente a abuso. Cubre el territorio de A07 (Fallos de autenticación) del Top Ten.
| Requisito | Texto (resumido) | Nivel |
|---|---|---|
| V2.1.1 | Las contraseñas tienen al menos 12 caracteres | L1–L3 |
| V2.1.7 | Las contraseñas se contrastan contra listas de comprometidas | L1–L3 |
| V2.2.1 | Existen controles anti-automatización (fuerza bruta, credential stuffing) | L1–L3 |
Ejemplo de verificación de V2.1.7 en el backend Node de BazarNube:
// V2.1.7: rechazar contrasenas presentes en listas de filtradas
const pwnedCount = await checkBreachedPassword(password); // p.ej. k-anonymity
if (pwnedCount > 0) {
return res.status(400).json({
error: 'Esta contrasena aparece en filtraciones conocidas. Elige otra.'
});
}
// V2.1.1: longitud minima
if (password.length < 12) {
return res.status(400).json({ error: 'Minimo 12 caracteres.' });
}V3 – Gestión de sesiones
Requisitos sobre cómo se crean, transportan, expiran e invalidan los tokens de sesión. Complementa a V2 en el territorio de A07.
| Requisito | Texto (resumido) | Nivel |
|---|---|---|
| V3.2.1 | Se generan tokens de sesión nuevos tras autenticarse (anti fixation) | L1–L3 |
| V3.3.1 | El logout y la expiración invalidan realmente el token | L1–L3 |
| V3.4.1 | Las cookies de sesión llevan atributos Secure, HttpOnly y SameSite |
L1–L3 |
Ejemplo de configuración de cookie de sesión que satisface V3.4.1 en Express:
// V3.4.1: cookie de sesion endurecida
res.cookie('sid', sessionId, {
httpOnly: true, // no accesible desde JavaScript (mitiga robo por XSS)
secure: true, // solo se envia por HTTPS
sameSite: 'lax', // mitiga CSRF en navegacion cross-site
maxAge: 1000 * 60 * 30 // expiracion (apoya V3.3.x)
});V4 – Control de acceso
El capítulo de autorización: quién puede acceder a qué. Cubre el territorio de A01 (Control de acceso roto), incluidos los IDOR que BazarNube sufría.
| Requisito | Texto (resumido) | Nivel |
|---|---|---|
| V4.1.1 | Las reglas de control de acceso se aplican en el servidor de confianza | L1–L3 |
| V4.1.3 | Principio de mínimo privilegio: solo se accede a lo autorizado | L1–L3 |
| V4.2.1 | Se verifica la propiedad del recurso antes de acceder (anti-IDOR) | L1–L3 |
Ejemplo de verificación de V4.2.1 corrigiendo el IDOR de los pedidos de BazarNube:
// V4.2.1: comprobar propiedad del recurso, no confiar en el ID del cliente
const pedido = await Pedido.findById(req.params.id);
if (!pedido || pedido.usuarioId !== req.user.id) {
return res.status(404).end(); // 404, no 403, para no revelar existencia
}
res.json(pedido);V5 – Validación, sanitización y codificación
El capítulo que concentra la defensa frente a inyección y XSS. Cubre el territorio de A03 (Inyección) y del XSS del módulo 3.
| Requisito | Texto (resumido) | Nivel |
|---|---|---|
| V5.1.1 | La entrada se valida contra un esquema/lista de permitidos | L1–L3 |
| V5.3.3 | Codificación de salida sensible al contexto (anti-XSS) | L1–L3 |
| V5.3.4 | Se usan consultas parametrizadas / ORM seguro (anti-inyección SQL) | L1–L3 |
Ejemplo de V5.3.4 sustituyendo la concatenación de SQL de BazarNube:
// MAL (inyeccion): const q = `SELECT * FROM productos WHERE nombre='${nombre}'`;
// V5.3.4: consulta parametrizada
const { rows } = await db.query(
'SELECT * FROM productos WHERE nombre = $1',
[nombre]
);V6 – Criptografía almacenada
Requisitos sobre cifrado en reposo, gestión de claves y aleatoriedad. Cubre el territorio de A02 (Fallos criptográficos).
| Requisito | Texto (resumido) | Nivel |
|---|---|---|
| V6.2.1 | Los datos sensibles se cifran en reposo | L1–L3 |
| V6.2.3 | Se usan algoritmos y modos aprobados, no obsoletos | L2–L3 |
| V6.4.1 | Las claves y secretos se gestionan con un almacén seguro (no en código) | L2–L3 |
Ejemplo de V6.4.1: los secretos no viven en el repositorio.
// V6.4.1: la clave se lee de un secret manager / variable de entorno,
// nunca hardcodeada en el codigo fuente
const dbKey = process.env.DB_ENCRYPTION_KEY; // inyectada por el secret store
if (!dbKey) throw new Error('Falta DB_ENCRYPTION_KEY en el entorno');V7 – Manejo de errores y logging
Requisitos sobre registrar eventos de seguridad sin filtrar datos sensibles. Cubre el territorio de A09 (Fallos de registro y monitorización).
| Requisito | Texto (resumido) | Nivel |
|---|---|---|
| V7.1.1 | No se registran datos sensibles (credenciales, tarjetas) en los logs | L1–L3 |
| V7.2.1 | Se registran los eventos de seguridad relevantes (login, acceso denegado) | L2–L3 |
| V7.3.1 | Los logs están protegidos frente a manipulación y son analizables | L2–L3 |
// V7.2.1: registrar evento de seguridad; V7.1.1: sin datos sensibles
logger.security('login_fallido', {
usuarioHash: hash(email), // no el email en claro; nunca la contrasena
ip: req.ip,
ts: Date.now()
});V8/V9 – Protección de datos y comunicaciones
- V8 (Protección de datos): minimización, retención, protección de datos sensibles en cliente y memoria. Cubre parte de A02 y A04 (Diseño inseguro).
- V9 (Comunicaciones): TLS bien configurado, cifrado en tránsito, sin protocolos débiles.
| Requisito | Texto (resumido) | Nivel |
|---|---|---|
| V8.1.1 | Se protegen datos sensibles frente a caché no autorizada | L2–L3 |
| V8.3.1 | Se minimiza y controla la retención de datos personales | L2–L3 |
| V9.1.1 | Toda comunicación usa TLS; sin fallback a texto plano | L1–L3 |
| V9.1.2 | Se usan versiones y suites TLS actuales; sin protocolos obsoletos | L2–L3 |
V14 – Configuración
Endurecimiento del despliegue: cabeceras de seguridad, dependencias, secretos, valores por defecto. Cubre A05 (Configuración incorrecta) y A06 (Componentes vulnerables).
| Requisito | Texto (resumido) | Nivel |
|---|---|---|
| V14.3.2 | Se eliminan configuraciones y cuentas por defecto innecesarias | L1–L3 |
| V14.4.1 | Se envían cabeceras de seguridad HTTP (CSP, HSTS, X-Content-Type-Options...) | L1–L3 |
| V14.2.1 | Las dependencias están al día y sin vulnerabilidades conocidas | L1–L3 |
// V14.4.1: cabeceras de seguridad con helmet en Express
app.use(helmet({
contentSecurityPolicy: { directives: { defaultSrc: ["'self'"] } },
hsts: { maxAge: 31536000, includeSubDomains: true }
}));Mapa: hallazgos Top Ten de BazarNube → requisitos ASVS
Este es el entregable central de la lección: convertir el backlog del módulo 3 (organizado por riesgos A01–A10) en requisitos ASVS verificables (organizados por capítulos V). Cada fila toma un hallazgo real de BazarNube y lo ancla a los requisitos que hay que verificar.
| Hallazgo BazarNube (M3) | Riesgo Top Ten | Requisitos ASVS a verificar | Cap. |
|---|---|---|---|
IDOR en /pedidos/:id |
A01 | V4.1.1, V4.2.1 | V4 |
| Secretos y clave de cifrado en el repo | A02 | V6.2.1, V6.4.1 | V6 |
| Datos de pago sin cifrar en reposo | A02 | V6.2.1, V8.1.1 | V6/V8 |
| SQL por concatenación en búsqueda | A03 | V5.1.1, V5.3.4 | V5 |
| Falta de threat modeling en el checkout | A04 | V1.1.x | V1 |
| Sin cabeceras de seguridad / defaults inseguros | A05 | V14.3.2, V14.4.1 | V14 |
| Librería con CVE conocido | A06 | V14.2.1 | V14 |
| XSS reflejado en el buscador | A03/XSS | V5.3.3, V5.3.4 | V5 |
| Contraseñas débiles y sin anti-fuerza bruta | A07 | V2.1.1, V2.1.7, V2.2.1 | V2 |
| Sesión no se invalida al cerrar sesión | A07 | V3.3.1, V3.4.1 | V3 |
| Sin registro de eventos de seguridad | A09 | V7.2.1, V7.3.1 | V7 |
| SSRF en "imagen desde URL" | A10 | V5.2.6, V12.6.x | V5/V12 |
Con este mapa, BazarNube ya no tiene "un montón de fixes sueltos": tiene una checklist ASVS por capítulos, con nivel asociado y estado verificable por cada fila. Ese es el insumo directo de la siguiente lección, donde lo convertiremos en un plan de implementación.
graph LR TT[Hallazgos Top Ten M3] --> MAP[Mapeo a requisitos ASVS] MAP --> CHK[Checklist por capitulos V] CHK --> VER[Verificacion cumple no-cumple]
Errores Comunes y Consejos
- Leer el requisito como consejo y no como test. Si tras leerlo no sabes decir cumple/no cumple, no lo has verificado; te falta mirar código o probar.
- Validar solo en el cliente. V4.1.1 y V5.1.1 exigen aplicar control de acceso y validación en el servidor; el front es ayuda de UX, no control de seguridad.
- Confundir codificación de salida con validación de entrada. Son requisitos distintos (V5.3 vs V5.1) y ambos hacen falta: validar entrada no exime de codificar la salida.
- Guardar secretos en el repositorio. V6.4.1 lo prohíbe explícitamente; usa un secret store o variables de entorno inyectadas.
- Consejo: trabaja capítulo a capítulo, no requisito aleatorio. Terminar V2 entero da una imagen de cumplimiento mucho más útil que picotear requisitos sueltos de varios capítulos.
Ejercicios
Ejercicio 1. Toma el hallazgo "XSS reflejado en el buscador" de BazarNube. Indica a qué capítulo(s) y requisito(s) ASVS lo mapearías y explica por qué intervienen tanto validación de entrada como codificación de salida.
Ejercicio 2. Lee este requisito y responde qué comprobarías en el código de BazarNube para marcarlo "cumple": "V3.4.1 – Verificar que las cookies de sesión usan los atributos Secure, HttpOnly y SameSite."
Ejercicio 3. El hallazgo "secretos en el repositorio" se mapeó a V6.4.1. Propón dos evidencias concretas que presentarías a un auditor para demostrar que ahora BazarNube cumple ese requisito.
Soluciones
Solución 1. Se mapea al capítulo V5 (Validación, sanitización y codificación), principalmente a V5.3.3 (codificación de salida sensible al contexto) y, de forma complementaria, a V5.1.1 (validación de entrada). Intervienen ambos porque son defensas distintas y acumulativas: validar la entrada reduce la superficie (rechazar caracteres/estructuras inesperadas), pero no basta, porque datos legítimos pueden contener caracteres peligrosos; la protección determinante frente a XSS es codificar la salida según el contexto (HTML, atributo, JS) en el punto de renderizado. Cumplir solo uno deja hueco; el ASVS exige ambos.
Solución 2. Buscaría en el código donde se emite la cookie de sesión (por ejemplo la config de express-session o el res.cookie('sid', ...)) y comprobaría que están puestos los tres atributos: httpOnly: true (no accesible desde JS, mitiga robo por XSS), secure: true (solo por HTTPS) y sameSite (lax o strict, mitiga CSRF). Si los tres están presentes en todos los caminos que crean la cookie, el requisito se marca cumple; si falta alguno o hay una ruta que emite la cookie sin ellos, no cumple.
Solución 3. (1) Evidencia de configuración: captura del secret manager / variables de entorno mostrando que DB_ENCRYPTION_KEY y demás secretos se inyectan en tiempo de ejecución, más el fragmento de código que los lee de process.env sin valores hardcodeados. (2) Evidencia de proceso/histórico: resultado de un escaneo de secretos (por ejemplo un secret scanner en CI) sobre el repositorio actual devolviendo cero hallazgos, y confirmación de que las claves antiguas expuestas fueron rotadas. Ambas juntas demuestran que los secretos ni están en el código ni son ya los que estuvieron expuestos.
Conclusión
Los requisitos del ASVS se organizan en capítulos temáticos —V2 autenticación, V3 sesiones, V4 control de acceso, V5 validación y codificación, V6 criptografía, V7 logging, V8/V9 datos y comunicaciones, V14 configuración— y cada uno se lee como un caso de prueba con respuesta cumple/no cumple/no aplica. Lo más valioso para BazarNube ha sido mapear los hallazgos del Top Ten del módulo 3 a requisitos ASVS concretos, transformando un backlog de riesgos sueltos en una checklist verificable por capítulos y niveles.
Tenemos el estándar, el nivel objetivo (L2) y la checklist mapeada. Falta lo que convierte todo esto en resultados: cómo integrarlo en el día a día del proyecto. En la última lección del módulo, 04-04 Implementación de ASVS en Proyectos, veremos cómo usar la checklist como criterios de aceptación, cuándo verificar manual o automáticamente, cómo dejar evidencias y trazabilidad, y trazaremos un plan práctico paso a paso para el backlog de BazarNube.
Curso de OWASP: Directrices y Estándares para la Seguridad en Aplicaciones Web
Módulo 1: Introducción a OWASP
Módulo 2: Principales Proyectos de OWASP
- OWASP Top Ten
- OWASP ASVS (Application Security Verification Standard)
- OWASP SAMM (Software Assurance Maturity Model)
- OWASP ZAP (Zed Attack Proxy)
- Otros Proyectos Clave: WSTG, Cheat Sheets y Dependency-Check
Módulo 3: OWASP Top Ten 2021 en Profundidad
- A01:2021 – Pérdida de Control de Acceso
- A02:2021 – Fallos Criptográficos y Exposición de Datos Sensibles
- A03:2021 – Inyección
- Cross-Site Scripting (XSS) en Profundidad
- A04:2021 – Diseño Inseguro
- A05:2021 – Configuración de Seguridad Incorrecta
- Entidades Externas XML (XXE)
- A06:2021 – Componentes Vulnerables y Desactualizados
- A07:2021 – Fallos de Identificación y Autenticación
- A08:2021 – Fallos de Integridad de Software y Datos (Deserialización Insegura)
- A09:2021 – Fallos de Registro y Monitorización
- A10:2021 – Server-Side Request Forgery (SSRF)
Módulo 4: OWASP ASVS (Application Security Verification Standard)
- Introducción a ASVS
- Niveles de Verificación
- Requisitos de Seguridad
- Implementación de ASVS en Proyectos
Módulo 5: OWASP SAMM (Software Assurance Maturity Model)
Módulo 6: OWASP ZAP (Zed Attack Proxy)
- Introducción a ZAP
- Instalación y Configuración
- Escaneo de Vulnerabilidades
- Automatización de Pruebas de Seguridad
Módulo 7: Buenas Prácticas y Recomendaciones
- Ciclo de Vida de Desarrollo Seguro (SDLC)
- Modelado de Amenazas (Threat Modeling)
- Integración de Seguridad en DevOps (DevSecOps)
- Capacitación y Concienciación en Seguridad
- Herramientas y Recursos Adicionales
Módulo 8: Ejercicios Prácticos y Casos de Estudio
- Ejercicio 1: Identificación de Vulnerabilidades
- Ejercicio 2: Implementación de Controles de Seguridad
- Caso de Estudio 1: Análisis de un Incidente de Seguridad
- Caso de Estudio 2: Mejora de la Seguridad en una Aplicación Web
