A la lliçó anterior vam recórrer l'escaneig dinàmic de BazarNube a mà: explorar, escanejar passiu i actiu, interpretar alertes i generar un informe. Funciona, però no escala: ningú no obrirà la GUI de ZAP cada vegada que en Marc fa un push. La seguretat que només passa "quan algú se'n recorda" no és seguretat. En aquesta última lliçó del mòdul portem ZAP al pipeline de CI/CD: convertim l'escaneig en un pas automàtic que corre en cada canvi, publica l'informe com a artefacte i trenca el build quan apareixen vulnerabilitats per sobre del llindar acordat. Aquest és el DAST dins d'un flux DevSecOps.
Nota èticolegal (segueix vigent). Automatitzar no canvia les regles: l'escaneig actiu ataca de debò. El pipeline ha d'apuntar sempre al staging propi i efímer de BazarNube (
https://staging.bazarnube.local), mai a producció ni a serveis de tercers. Automatitzar un atac contra un sistema aliè el fa més perillós, no menys.
Contingut
- Per què automatitzar el DAST
- Els scripts empaquetats: baseline scan i full scan amb Docker
- El fitxer de regles per gestionar falsos positius
- L'Automation Framework (YAML amb jobs)
- L'API i el mode daemon de ZAP
- Integració en GitHub Actions
- Integració en GitLab CI
- Llindars, fallada de build i informes com a artefactes
- Un pipeline DAST complet per a BazarNube
- Errors comuns i consells
- Exercicis
- Conclusió
Per què automatitzar el DAST
Automatitzar l'escaneig dinàmic persegueix tres objectius:
- Repetibilitat: el mateix escaneig, amb la mateixa política, cada vegada. Sense passos oblidats.
- Detecció primerenca: una vulnerabilitat trobada al pipeline costa molt menys que una trobada en producció.
- Governança: el pipeline pot bloquejar un desplegament si apareix alguna cosa greu, aplicant una política objectiva en lloc d'un criteri individual.
flowchart LR
A[Push / MR a BazarNube] --> B[Build i deploy a staging]
B --> C[ZAP DAST en contenidor]
C --> D{Alertes > llindar?}
D -->|Si| E[Build FAIL, bloqueja deploy]
D -->|No| F[Build OK, publica informe]
E --> G[Informe artefacte]
F --> G
Els scripts empaquetats: baseline scan i full scan amb Docker
ZAP publica scripts llestos per a CI dins de la imatge zaproxy/zap-stable (abans owasp/zap2docker-stable). Els dos que importen:
| Script | Què fa | Ataca activament | Durada | Quan usar-lo |
|---|---|---|---|---|
zap-baseline.py |
Spider + escaneig passiu; reporta capçaleres, cookies, fugues | No | Curt (minuts) | En cada PR/commit, gate ràpid |
zap-full-scan.py |
Spider + AJAX Spider + escaneig actiu complet | Sí | Llarg (desenes de min) | Nocturn o pre-release |
zap-api-scan.py |
Escaneig guiat per definició OpenAPI/SOAP/GraphQL | Sí | Variable | APIs (la de BazarNube) |
Estratègia per a BazarNube: zap-baseline.py en cada Pull Request (ràpid, no invasiu, apte com a gate) i zap-full-scan.py en un job nocturn contra l'staging dedicat (lent i agressiu, però fora del camí crític dels desenvolupadors).
Exemple de baseline contra staging, muntant un volum per recollir informes:
docker run --rm -v "$(pwd)/zap-out:/zap/wrk/:rw" \
-t zaproxy/zap-stable zap-baseline.py \
-t https://staging.bazarnube.local \
-r baseline-report.html \
-J baseline-report.json \
-w baseline-report.md \
-c bazarnube-rules.confFlags clau:
-tURL objectiu (sempre staging propi).-r/-J/-winformes en HTML, JSON i Markdown.-cfitxer de regles (falsos positius, veure a sota).-Ino fallar el build davant alertes de nivell Info (només retornar error per WARN/FAIL).-lnivell mínim que provoca fallada (PASS,IGNORE,INFO,WARN,FAIL).
El full scan és idèntic en forma, canviant l'script:
docker run --rm -v "$(pwd)/zap-out:/zap/wrk/:rw" \
-t zaproxy/zap-stable zap-full-scan.py \
-t https://staging.bazarnube.local \
-r full-report.html -J full-report.json \
-c bazarnube-rules.confEl fitxer de regles per gestionar falsos positius
A 06-03 vam fer triage manual marcant falsos positius a la GUI. En CI això no val: necessitem que la decisió sigui codi versionat. El fitxer de regles (-c) permet fixar el tractament de cada regla pel seu ID. Format: ID<TAB>acció<TAB>URL-regex(opcional).
# bazarnube-rules.conf
# ID Accio URL (opcional)
10096 IGNORE # Timestamp Disclosure: soroll, no aplica a BazarNube
10021 IGNORE # X-Content-Type-Options en assets estatics del CDN
10035 WARN # Strict-Transport-Security: avisar, no trencar build encara
40012 FAIL # Reflected XSS: sempre trenca el build
40018 FAIL # SQL Injection: sempre trenca el buildAccions possibles: IGNORE (no reportar), WARN (reportar sense fallar el build) i FAIL (reportar i trencar el build). Així el tractament dels falsos positius viu al repositori, es revisa en un PR i queda auditat: res de decisions invisibles.
L'Automation Framework (YAML amb jobs)
Els scripts són còmodes però rígids. Per a escaneigs amb context, autenticació i política a mida (com els que vam definir a 06-02 i 06-03), ZAP ofereix l'Automation Framework: un únic fitxer YAML que descriu l'escaneig com una llista de jobs encadenats. És la forma recomanada per a casos seriosos.
# zap-bazarnube.yaml
env:
contexts:
- name: BazarNube
urls:
- https://staging.bazarnube.local
includePaths:
- "https://staging.bazarnube.local.*"
excludePaths:
- "https://staging.bazarnube.local/logout.*"
- ".*pay\\.tercero\\.com.*"
authentication:
method: form
parameters:
loginPageUrl: https://staging.bazarnube.local/login
loginRequestUrl: https://staging.bazarnube.local/api/auth/login
loginRequestBody: "username={%username%}&password={%password%}"
users:
- name: venedor
credentials:
username: [email protected]
password: ${BZN_TEST_PASS}
parameters:
failOnError: true
jobs:
- type: spider
parameters:
context: BazarNube
user: venedor
- type: spiderAjax
parameters:
context: BazarNube
user: venedor
- type: passiveScan-wait
- type: activeScan
parameters:
context: BazarNube
user: venedor
policy: BazarNube-Web
- type: report
parameters:
template: traditional-html
reportFile: zap-bazarnube.html
- type: report
parameters:
template: traditional-json
reportFile: zap-bazarnube.jsonS'executa amb:
docker run --rm -v "$(pwd):/zap/wrk/:rw" \
-t zaproxy/zap-stable zap.sh -cmd -autorun /zap/wrk/zap-bazarnube.yamlFixa't que la contrasenya de prova arriba per variable d'entorn (${BZN_TEST_PASS}), injectada des del gestor de secrets del CI: mai credencials al YAML.
L'API i el mode daemon de ZAP
Per a control total (integrar ZAP amb scripts propis, orquestrar des de Python/Node), s'arrenca ZAP com a daemon sense GUI i se li parla per la seva API REST:
# ZAP headless escoltant al 8080, amb clau d'API obligatoria
docker run -u zap -p 8080:8080 -d --name zap zaproxy/zap-stable \
zap.sh -daemon -host 0.0.0.0 -port 8080 \
-config api.key=$ZAP_KEY \
-config api.addrs.addr.name=.* -config api.addrs.addr.regex=true-daemonarrenca sense interfície gràfica.-config api.key=...protegeix l'API amb una clau (obligatòria; no la deixis buida).- Endpoints REST sota
/JSON/...per llançar spider, active scan, llegir alertes i generar informes (ja els vam usar a 06-03).
Molts equips fan servir la llibreria client oficial en lloc de curl cru:
from zapv2 import ZAPv2
zap = ZAPv2(apikey='CLAU', proxies={'http': 'http://localhost:8080'})
zap.spider.scan('https://staging.bazarnube.local')
zap.ascan.scan('https://staging.bazarnube.local', scanpolicyname='BazarNube-Web')
alerts = zap.core.alerts(baseurl='https://staging.bazarnube.local')Integració en GitHub Actions
A GitHub, el flux típic és aixecar staging, executar el baseline en cada PR i pujar l'informe com a artefacte. Existeix l'acció oficial zaproxy/action-baseline:
# .github/workflows/dast.yml
name: DAST BazarNube
on: [pull_request]
jobs:
zap-baseline:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Aixecar staging de BazarNube
run: docker compose -f docker-compose.staging.yml up -d --wait
- name: ZAP Baseline Scan
uses: zaproxy/[email protected]
with:
target: 'https://staging.bazarnube.local'
rules_file_name: 'bazarnube-rules.conf'
cmd_options: '-J baseline-report.json -w baseline-report.md'
fail_action: true
- name: Publicar informe com a artefacte
if: always()
uses: actions/upload-artifact@v4
with:
name: zap-report
path: |
report_html.html
baseline-report.json
baseline-report.mdfail_action: true fa que les alertes marcades com a FAIL trenquin el job (i per tant bloquegin el merge si el check és obligatori). El pas upload-artifact amb if: always() garanteix que l'informe es guarda encara que el build falli, que és just quan més el necessites.
Integració en GitLab CI
A GitLab el patró és equivalent fent servir la imatge de ZAP com a imatge del job:
# .gitlab-ci.yml
dast_baseline:
stage: test
image: zaproxy/zap-stable
variables:
TARGET: "https://staging.bazarnube.local"
script:
- mkdir -p zap-out
- zap-baseline.py -t "$TARGET"
-c bazarnube-rules.conf
-r zap-out/report.html -J zap-out/report.json
|| EXIT=$?
- echo "ZAP exit code $EXIT"
- '[ "${EXIT:-0}" -lt 2 ] || exit 1' # 2 = WARN, 3 = FAIL -> trenca build
artifacts:
when: always
paths:
- zap-out/
expire_in: 30 daysAquí gestionem el codi de sortida a mà: ZAP retorna 0 (tot OK), 1 (error intern), 2 (hi ha WARN) i 3 (hi ha FAIL). Decidim el llindar a la mateixa lògica del job. artifacts: when: always compleix la mateixa funció que a GitHub: conservar l'informe encara que el job falli.
Llindars, fallada de build i informes com a artefactes
La política de "quan trencar el build" és una decisió d'equip, no tècnica. Una progressió sana per a BazarNube:
| Fase d'adopció | Què trenca el build | Objectiu |
|---|---|---|
| Introducció | Res (WARN en tot) |
Guanyar visibilitat sense frustrar l'equip |
| Consolidació | Només High confirmades (SQLi, XSS) |
Bloquejar el greu, tolerar el soroll |
| Maduresa | High i Medium segons regles |
Elevar el llistó progressivament |
Codis de sortida dels scripts, per configurar el gate:
| Codi | Significat | Acció recomanada en CI |
|---|---|---|
0 |
Sense troballes per sobre del llindar | Continuar |
1 |
Error d'execució de ZAP | Fallar i investigar |
2 |
Almenys un WARN |
Segons política (avisar o fallar) |
3 |
Almenys un FAIL |
Fallar el build |
I sempre publica els informes (HTML per a humans, JSON per comparar entre builds, Markdown per enganxar al ticket) com a artefactes amb if: always() / when: always.
Un pipeline DAST complet per a BazarNube
Ajuntant-ho tot, l'estratègia de BazarNube combina dos gates de cost diferent:
flowchart TD
A[PR obert] --> B[Deploy efimer a staging]
B --> C[zap-baseline.py amb rules.conf]
C --> D{FAIL?}
D -->|Si| E[Bloqueja merge + artefacte]
D -->|No| F[Merge permes + artefacte]
G[Cron nocturn] --> H[Deploy staging estable]
H --> I[zap-full-scan.py autenticat]
I --> J[Informe al backlog: BZN-xxx]
- Per PR:
zap-baseline.py(ràpid, no invasiu) com a gate obligatori. Només trenca el build davantFAIL(SQLi/XSS confirmades). - Nocturn:
zap-full-scan.pyo l'Automation Framework autenticat (lent, agressiu) contra staging dedicat. No bloqueja ningú; les seves troballes entren com a ticketsBZN-xxxal backlog, ja mapejats al Top Ten (06-03).
Així el desenvolupador té feedback ràpid al seu PR i l'escaneig profund passa sense frenar el flux de treball. L'SRE manté el staging efímer; la Lucía i en Marc reben tickets accionables en lloc d'un PDF enorme cada trimestre.
Errors Comuns i Consells
- Escanejar un staging que no està llest. Si el DAST arrenca abans que l'app respongui, no explora res. Fes servir
--wait/healthchecks abans de llançar ZAP. - Deixar l'API sense clau.
-config api.key=buit exposa el daemon. Genera una clau i passa-la per secret del CI. - Credencials o claus al YAML. Tot secret (contrasenya de prova,
ZAP_KEY) va per variables/secrets del CI, mai versionat. - Posar el full scan com a gate de cada PR. És massa lent i agressiu; frustra l'equip i alenteix el merge. Baseline en PR, full scan nocturn.
- No publicar l'informe quan el build falla. Sense
if: always()/when: alwaysperds just l'informe de la fallada. - Gestionar falsos positius "a ull" cada execució. Posa'ls al fitxer de regles versionat; que es revisin en un PR.
- Posar el llistó al màxim des del dia u. Si tot trenca el build de cop, l'equip desactivarà l'escaneig. Puja el llindar per fases.
Exercicis
Exercici 1. En Marc proposa posar zap-full-scan.py com a gate obligatori en cada Pull Request de BazarNube. Explica per què no és bona idea i quina estratègia de dos nivells proposaries en el seu lloc.
Exercici 2. El baseline reporta insistentment l'alerta 10096 (Timestamp Disclosure), que l'equip ja ha verificat com a fals positiu. Escriu la línia del fitxer bazarnube-rules.conf per silenciar-la i explica per què això és millor que marcar-ho a la GUI.
Exercici 3. A GitLab, el teu job de ZAP acaba amb codi de sortida 3 però el pipeline apareix en verd. Què està passant i com ho corregeixes perquè aquest cas trenqui el build i conservi l'informe?
Solucions
Solució 1. El full scan fa escaneig actiu complet amb Spider i AJAX Spider: triga desenes de minuts i ataca de debò, per la qual cosa com a gate de cada PR alentiria el desenvolupament i generaria fricció. Estratègia recomanada: baseline en cada PR (ràpid, passiu, trenca el build només davant FAIL) i full scan nocturn contra un staging dedicat, les troballes del qual entren al backlog com a tickets sense bloquejar ningú.
Solució 2. Línia del fitxer de regles:
És millor que la GUI perquè la decisió queda versionada al repositori: es revisa en un PR, té autor i data, s'aplica idèntica en cada execució del CI i és auditable. Un Mark as False Positive a la GUI viu només a la sessió local d'una persona i no es propaga al pipeline.
Solució 3. L'script retorna 3 (hi ha alertes FAIL), però el job no propaga aquest codi perquè probablement es va capturar amb || true o no es tradueix a exit 1. Cal avaluar el codi de sortida i forçar la fallada, a més de conservar artefactes sempre:
script:
- zap-baseline.py -t "$TARGET" -c bazarnube-rules.conf -r zap-out/report.html || EXIT=$?
- '[ "${EXIT:-0}" -lt 2 ] || exit 1'
artifacts:
when: always
paths: [ zap-out/ ]Amb [ "${EXIT:-0}" -lt 2 ] || exit 1, qualsevol codi >= 2 (WARN/FAIL) trenca el build, i when: always garanteix que l'informe es puja fins i tot en la fallada.
Conclusió
Amb aquesta lliçó tanques el Mòdul 6. Has passat d'executar ZAP a mà a integrar-lo en un pipeline DevSecOps: baseline i full scan amb Docker, l'Automation Framework per a escaneigs autenticats a mida, l'API en mode daemon, pipelines reals en GitHub Actions i GitLab CI, gestió de llindars i fallada de build, informes com a artefactes i un fitxer de regles versionat per als falsos positius. El resultat és un DAST que corre sol, en cada canvi, i protegeix BazarNube sense dependre que algú se'n recordi.
Aquest és també el punt on tot el curs convergeix. ZAP no viu aïllat: és una peça dins d'un SDLC segur. Al Mòdul 7 fem aquest salt: el cicle de vida de desenvolupament segur, el modelatge d'amenaces per decidir què protegir abans d'escriure codi, i DevSecOps com a filosofia que fila tot l'après. Allà encaixaràs les peces: el Top Ten 2021 (M3) com a catàleg de riscos, l'ASVS (M4) com a requisits verificables, SAMM (M5) com a model de maduresa del programa, i ZAP (M6) com la verificació dinàmica automatitzada dins del pipeline. La seguretat deixa de ser una fase final per convertir-se en una propietat contínua del procés.
Curs d'OWASP: Directrius i Estàndards per a la Seguretat en Aplicacions Web
Mòdul 1: Introducció a OWASP
Mòdul 2: Principals Projectes d'OWASP
- OWASP Top Ten
- OWASP ASVS (Application Security Verification Standard)
- OWASP SAMM (Software Assurance Maturity Model)
- OWASP ZAP (Zed Attack Proxy)
- Altres Projectes Clau: WSTG, Cheat Sheets i Dependency-Check
Mòdul 3: OWASP Top Ten 2021 en Profunditat
- A01:2021 – Pèrdua de Control d'Accés
- A02:2021 – Errors Criptogràfics i Exposició de Dades Sensibles
- A03:2021 – Injecció
- Cross-Site Scripting (XSS) en Profunditat
- A04:2021 – Disseny Insegur
- A05:2021 – Configuració de Seguretat Incorrecta
- Entitats Externes XML (XXE)
- A06:2021 – Components Vulnerables i Desactualitzats
- A07:2021 – Errors d'Identificació i Autenticació
- A08:2021 – Errors d'Integritat de Programari i Dades (Deserialització Insegura)
- A09:2021 – Errors de Registre i Monitorització
- A10:2021 – Server-Side Request Forgery (SSRF)
Mòdul 4: OWASP ASVS (Application Security Verification Standard)
Mòdul 5: OWASP SAMM (Software Assurance Maturity Model)
Mòdul 6: OWASP ZAP (Zed Attack Proxy)
- Introducció a ZAP
- Instal·lació i Configuració
- Escaneig de Vulnerabilitats
- Automatització de Proves de Seguretat
Mòdul 7: Bones Pràctiques i Recomanacions
- Cicle de Vida de Desenvolupament Segur (SDLC)
- Modelatge d'Amenaces (Threat Modeling)
- Integració de Seguretat en DevOps (DevSecOps)
- Formació i Conscienciació en Seguretat
- Eines i Recursos Addicionals
Mòdul 8: Exercicis Pràctics i Casos d'Estudi
- Exercici 1: Identificació de Vulnerabilitats
- Exercici 2: Implementació de Controls de Seguretat
- Cas d'Estudi 1: Anàlisi d'un Incident de Seguretat
- Cas d'Estudi 2: Millora de la Seguretat en una Aplicació Web
