En la lección anterior dejamos ZAP listo para trabajar: el certificado raíz confiado, el proxy enrutando el tráfico de BazarNube y un contexto con scope y autenticación bien definidos. Toda esa preparación tenía un objetivo: llegar hasta las zonas donde de verdad hay riesgo. Ahora ponemos la maquinaria en marcha. En esta lección recorreremos el flujo completo de un escaneo dinámico (DAST) sobre el staging de BazarNube: exploraremos la aplicación con el spider y el AJAX Spider, dejaremos trabajar al escáner pasivo, lanzaremos el escáner activo con una política adecuada, aprenderemos a interpretar las alertas por riesgo y confianza, haremos triage de falsos positivos y generaremos informes que mapeen los hallazgos al Top Ten 2021 y al backlog del equipo.
Nota ético-legal (imprescindible). Un escaneo activo envía ataques reales (payloads de inyección, cargas que modifican datos, peticiones masivas). Ejecútalo únicamente contra sistemas de tu propiedad o con permiso explícito por escrito. En este curso siempre trabajamos sobre
https://staging.bazarnube.local, un entorno propio, aislado y con datos ficticios. Nunca apuntes ZAP en modo attack a producción ni a terceros como la pasarelapay.tercero.com.
Contenido
- El flujo de un escaneo de principio a fin
- Fase 1: explorar con el Spider y el AJAX Spider
- Fase 2: el escáner pasivo
- Fase 3: el escáner activo y las políticas de escaneo
- Interpretar alertas: riesgo y confianza
- Triage de falsos positivos
- Mapeo de alertas de ZAP al Top Ten 2021 y al backlog de BazarNube
- Generación de informes (HTML, JSON, Markdown)
- Errores comunes y consejos
- Ejercicios
- Conclusión
El flujo de un escaneo de principio a fin
Un escaneo DAST no es un botón mágico: es una secuencia. ZAP solo puede atacar lo que conoce, así que primero hay que descubrir la superficie (URLs, formularios, parámetros, endpoints de API) y después probarla. El orden es siempre el mismo:
flowchart LR
A[Contexto y auth listos] --> B[Explorar: Spider]
B --> C[Explorar: AJAX Spider]
C --> D[Escaneo pasivo automatico]
D --> E[Escaneo activo con policy]
E --> F[Triage de alertas]
F --> G[Informe HTML / JSON / MD]
G --> H[Backlog de BazarNube]
Cada fase alimenta a la siguiente: cuanto mejor sea la exploración, más completo será el árbol de sitios (Sites tree) y más superficie tendrá el escáner activo para probar. Un escaneo con mala cobertura da una falsa sensación de seguridad: "0 alertas altas" no significa nada si el spider no llegó al 60% de la aplicación.
Fase 1: explorar con el Spider y el AJAX Spider
Spider tradicional
El Spider parte de una o varias URLs semilla y sigue los enlaces href, src y las acciones de formulario que encuentra en el HTML. Es rápido y barato, pero solo ve lo que está en el HTML estático. Para lanzarlo sobre nuestro contexto autenticado:
- Clic derecho sobre el nodo raíz de BazarNube en el Sites tree >
Attack > Spider.... - Selecciona el Context y el User que definimos en 06-02, para que explore ya autenticado como vendedor.
- Deja marcada la opción de respetar el scope del contexto.
Desde la línea de comandos vía API (lo veremos en detalle en 06-04) sería:
# Semilla de exploracion dentro del scope de staging
curl "http://localhost:8080/JSON/spider/action/scan/?apikey=$ZAP_KEY&contextName=BazarNube&url=https://staging.bazarnube.local/"AJAX Spider
BazarNube tiene un frontend React: gran parte de la navegación y los datos se cargan por JavaScript, y el catálogo se pinta con llamadas fetch a la API. El Spider tradicional no ejecuta JavaScript, así que se perdería casi todo el marketplace. Para eso está el AJAX Spider, que controla un navegador real (Firefox/Chrome headless) y explora la aplicación como lo haría un usuario, disparando eventos y capturando las peticiones XHR.
| Aspecto | Spider tradicional | AJAX Spider |
|---|---|---|
| Ejecuta JavaScript | No | Sí (navegador real) |
| Velocidad | Muy rápido | Lento |
| Cobertura en SPA (React) | Baja | Alta |
| Consumo de recursos | Bajo | Alto (CPU/RAM) |
| Cuándo usarlo | Sitios clásicos, APIs enlazadas | SPAs, mucho contenido dinámico |
Regla práctica para BazarNube: ejecuta primero el Spider tradicional (barato, cubre la API y las rutas server-rendered del legacy Java) y a continuación el AJAX Spider para el frontend React. La unión de ambos da la mejor cobertura.
Para las APIs REST/GraphQL, la mejor "exploración" no es el spider sino importar la definición: ZAP puede consumir un fichero OpenAPI/Swagger o una colección, poblando el árbol con todos los endpoints y sus parámetros. Si BazarNube publica
openapi.json, impórtalo antes de escanear.
Fase 2: el escáner pasivo
Mientras exploras (y mientras navegas manualmente por el proxy), el escáner pasivo trabaja en segundo plano: no envía ni una sola petición extra. Se limita a observar las peticiones y respuestas que ya pasan por ZAP y a detectar problemas visibles sin atacar:
- Cabeceras de seguridad ausentes (
Content-Security-Policy,Strict-Transport-Security,X-Content-Type-Options). - Cookies sin
Secure,HttpOnlyoSameSite. - Fugas de información (versiones de servidor, comentarios, mensajes de error, tokens en URL).
- Recursos servidos por HTTP dentro de HTTPS (mixed content).
Como no ataca, el escaneo pasivo es seguro incluso en producción y es el motor detrás del modo safe que vimos en 06-01. Es el primer sitio donde mirar: muchas de las "victorias rápidas" de BazarNube (cabeceras y flags de cookie) salen aquí sin coste ni riesgo.
Fase 3: el escáner activo y las políticas de escaneo
El escáner activo es donde ZAP realmente ataca: coge cada URL y cada parámetro descubiertos e inyecta payloads para provocar comportamientos vulnerables (comillas para SQLi, scripts para XSS, rutas para path traversal, etc.). Por eso solo se lanza sobre staging propio.
Anatomía de una política de escaneo (Scan Policy)
Una Scan Policy define qué familias de ataque se ejecutan y con qué intensidad. Se gestiona en Analyse > Scan Policy Manager. Sus dos ejes son:
- Threshold (umbral): cómo de "seguro" debe estar ZAP antes de reportar.
Lowreporta más (y genera más falsos positivos);Highreporta solo cuando está muy seguro.Offdesactiva esa familia. - Strength (fuerza): cuántos payloads prueba por parámetro.
Lowes rápido;Insanees exhaustivo pero lento y ruidoso.
| Familia de reglas activas | Threshold | Strength | Justificación en BazarNube |
|---|---|---|---|
| SQL Injection | Medium | High | Hay backend PostgreSQL y consultas legacy Java; prioritario |
| Cross Site Scripting | Medium | High | Reflejado y almacenado; el catálogo pinta datos de vendedor |
| Path Traversal / LFI | Medium | Medium | Descarga de facturas por parámetro de fichero |
| Server Side Request Forgery | Medium | Medium | Servicio de "importar producto por URL" |
| Remote Code Execution | Medium | Medium | Cobertura del Top Ten |
| External redirect | Low | Low | Ruido bajo, útil detectarlo |
Crea una política a medida (por ejemplo BazarNube-Web) en lugar de usar la de por defecto: acota el tiempo de escaneo y evita ruido irrelevante. Para lanzar el activo: clic derecho sobre el contexto > Attack > Active Scan..., elige el User autenticado y la Policy creada.
# Escaneo activo por API, con contexto, usuario y politica propios
curl "http://localhost:8080/JSON/ascan/action/scan/?apikey=$ZAP_KEY&contextId=1&userId=1&scanPolicyName=BazarNube-Web&recurse=true"Interpretar alertas: riesgo y confianza
Cada hallazgo es una alerta con dos ejes independientes que no hay que confundir:
- Riesgo (Risk): el impacto potencial si es real. Niveles: High, Medium, Low, Informational.
- Confianza (Confidence): cómo de seguro está ZAP de que no es un falso positivo. Niveles: Confirmed, High, Medium, Low, False Positive (este último lo marcas tú tras el triage).
Un hallazgo High risk / Low confidence no se ignora: se verifica manualmente, porque si se confirma es de los más graves. Y un Low risk / High confidence puede ser una corrección trivial que conviene cerrar ya. Prioriza cruzando ambos ejes:
flowchart TD
A[Nueva alerta] --> B{Risk?}
B -->|High/Medium| C{Confidence?}
B -->|Low/Info| D[Backlog normal o victoria rapida]
C -->|High/Confirmed| E[Verificar y abrir hallazgo prioritario]
C -->|Low/Medium| F[Reproducir manualmente antes de reportar]
Triage de falsos positivos
DAST genera falsos positivos: es normal y esperable. El triage es el trabajo de separar lo real de lo espurio antes de molestar a Lucía o a Marc con un ticket. Proceso recomendado por alerta:
- Lee la evidencia que da ZAP: la petición atacante y el fragmento de respuesta que disparó la regla (pestaña Response con el highlight).
- Reprodúcelo con el Request Editor o
curl: ¿el comportamiento se sostiene fuera de ZAP? - Contrasta con el código cuando puedas: un XSS reflejado reportado sobre un valor que el frontend escapa con React puede ser falso.
- Decide: si es real, se queda; si es espurio, clic derecho >
Mark as False Positive(o súbele el threshold de esa regla). Documenta por qué.
Un falso positivo mal cerrado es tan peligroso como no escanear: si marcas como FP algo real, lo entierras. Deja siempre una nota del razonamiento.
Mapeo de alertas de ZAP al Top Ten 2021 y al backlog de BazarNube
Las alertas de ZAP hablan el idioma de las scan rules; el negocio y el backlog hablan el idioma del Top Ten 2021 (que vimos en M3). Traducir de uno a otro es lo que convierte un informe técnico en trabajo priorizado. Esta es la tabla de correspondencia para BazarNube:
| Alerta de ZAP | Riesgo típico | Categoría OWASP Top Ten 2021 | Hallazgo del backlog de BazarNube |
|---|---|---|---|
| SQL Injection | High | A03: Injection | BZN-112 login del legacy Java concatena SQL |
| Cross Site Scripting (Reflected) | High | A03: Injection | BZN-087 buscador refleja q sin escapar |
| Path Traversal | High | A01: Broken Access Control | BZN-140 descarga de factura por file= |
| Absence of Anti-CSRF Tokens | Medium | A01: Broken Access Control | BZN-095 formularios del panel vendedor |
| Server Side Request Forgery | High | A10: SSRF | BZN-131 "importar producto por URL" |
| Application Error Disclosure | Low | A05: Security Misconfiguration | BZN-060 stack traces de Spring Boot |
| CSP Header Not Set | Medium | A05: Security Misconfiguration | BZN-041 falta CSP en el frontend React |
| Cookie without HttpOnly/SameSite | Low | A05: Security Misconfiguration | BZN-039 cookie de sesión del panel |
| Vulnerable JS Library | Medium | A06: Vulnerable Components | BZN-118 librería frontend desactualizada |
Ojo con el IDOR. El Broken Access Control de tipo IDOR (acceso a un pedido ajeno cambiando el
id) que estudiamos en M3 es difícil de detectar para un DAST genérico, porque ZAP no sabe qué recurso "debería" ver cada usuario. ZAP tiene el complemento Access Control Testing, pero requiere que definas dos usuarios con roles distintos y las reglas de acceso esperadas. No confíes en el escáner activo para el control de acceso: complétalo con pruebas manuales o de negocio.
Generación de informes (HTML, JSON, Markdown)
Con el triage hecho, se genera el informe. Desde la GUI: Report > Generate Report.... ZAP ofrece plantillas según el destinatario:
| Formato | Plantilla ZAP típica | Destinatario | Uso |
|---|---|---|---|
| HTML | traditional-html / risk-confidence-html |
Lucía, dirección | Lectura humana, evidencias visibles |
| JSON | traditional-json |
Automatización / SIEM | Parsear, comparar entre builds |
| Markdown | traditional-md |
Backlog / repositorio | Pegar en un ticket o PR |
| XML | traditional-xml |
Herramientas legacy | Integración con otras suites |
Por API o CLI (anticipando 06-04):
# Informe HTML por riesgo y confianza
curl "http://localhost:8080/OTHER/core/other/htmlreport/?apikey=$ZAP_KEY" -o zap-bazarnube.html
# Volcado JSON de todas las alertas para procesar en el pipeline
curl "http://localhost:8080/JSON/core/view/alerts/?apikey=$ZAP_KEY&baseurl=https://staging.bazarnube.local" -o alerts.jsonEl informe no es el final del trabajo: es la entrada del backlog. Cada alerta confirmada se convierte en un BZN-xxx con su categoría del Top Ten, su evidencia y su prioridad por riesgo.
Errores Comunes y Consejos
- Lanzar el activo sin haber explorado. Si el árbol de sitios está vacío, el escáner activo no ataca nada. Explora (Spider + AJAX Spider o import OpenAPI) antes.
- Olvidar la autenticación. Si ZAP pierde la sesión a mitad de escaneo, todo lo autenticado queda sin probar. Verifica los indicadores de sesión del contexto (06-02) y añade
/logouta las exclusiones. - Confundir riesgo con confianza. Son ejes distintos. Un High risk / Low confidence se verifica, no se descarta.
- Escanear producción "solo un poco". No existe un activo "suave" seguro: modifica datos y genera carga. Solo staging propio.
- Fiarse del "0 altas". Sin cobertura, cero alertas no es tranquilidad. Mira siempre cuántas URLs se exploraron.
- No documentar los falsos positivos. Un FP sin justificación es deuda oculta; el siguiente que lo vea no sabrá si fiarse.
- Esperar que ZAP encuentre IDOR/lógica de negocio. El DAST cubre inyecciones y misconfig; el control de acceso fino y la lógica requieren prueba manual.
Ejercicios
Ejercicio 1. El equipo se queja de que ZAP "no encuentra casi nada" en el catálogo de BazarNube, que es un React SPA. El árbol de sitios muestra solo la home y /login. ¿Qué ha fallado en la fase de exploración y cómo lo corriges?
Ejercicio 2. ZAP reporta una alerta "Cross Site Scripting (Reflected)" con Risk: High y Confidence: Low sobre el parámetro q del buscador. Describe el proceso de triage paso a paso antes de abrir (o no) el ticket BZN-087.
Ejercicio 3. Tienes que priorizar tres alertas para la reunión con Lucía: (A) SQL Injection, High/Confirmed; (B) CSP Header Not Set, Medium/High; (C) Application Error Disclosure, Low/High. Ordénalas y mapea cada una a su categoría del Top Ten 2021.
Soluciones
Solución 1. Solo se ejecutó el Spider tradicional, que no ejecuta JavaScript, así que no vio el catálogo cargado por React. La corrección es lanzar el AJAX Spider (que usa un navegador real) sobre el mismo contexto autenticado y, si BazarNube publica una definición OpenAPI de su API, importarla para poblar todos los endpoints. Después se relanza el escaneo con el árbol ya completo.
Solución 2. (1) Abrir la alerta y leer la evidencia: la petición inyectada y el fragmento de respuesta resaltado. (2) Reproducir con el Request Editor o curl para ver si el payload vuelve sin escapar en la respuesta HTML (no solo en un JSON que el front nunca renderiza como HTML). (3) Comprobar si el valor termina realmente en el DOM sin escapar; si React lo pinta con {q} lo escapa por defecto (posible FP), pero si se usa dangerouslySetInnerHTML o se inserta server-side, es real. (4) Si se confirma, abrir BZN-087 como A03 Injection prioritario; si es espurio, marcar False Positive con nota del motivo.
Solución 3. Orden de prioridad: A > B > C.
- (A) SQL Injection, High/Confirmed -> A03: Injection. Máxima prioridad: confirmada y de alto impacto.
- (B) CSP Header Not Set, Medium/High -> A05: Security Misconfiguration. Importante y de corrección barata.
- (C) Application Error Disclosure, Low/High -> A05: Security Misconfiguration. Real pero de bajo impacto; victoria rápida.
Conclusión
Ya dominas el ciclo completo de un escaneo dinámico en ZAP: explorar con Spider y AJAX Spider, dejar trabajar al pasivo, atacar con el activo usando una política a medida, interpretar las alertas por riesgo y confianza, hacer triage de falsos positivos, mapear cada hallazgo al Top Ten 2021 y al backlog de BazarNube, y empaquetarlo en un informe accionable. Todo ello, siempre, contra tu propio staging.
Hacer esto a mano cada vez que se toca el código no escala. En la última lección del módulo, 06-04 Automatización de Pruebas de Seguridad, llevaremos ZAP al pipeline: zap-baseline.py y zap-full-scan.py con Docker, el Automation Framework en YAML, la API en modo daemon, y pipelines completos de GitHub Actions y GitLab CI que ejecutan un DAST sobre BazarNube en cada cambio, publican el informe como artefacto y rompen el build cuando aparecen vulnerabilidades por encima del umbral.
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
