El mòdul anterior va acabar assenyalant una paraula que va aparèixer a les seves sis lliçons sense desenvolupar-se mai: verificar. El registre de riscos afirma que el port 5432 està exposat, el catàleg de controls promet un escaneig extern mensual que ningú no ha executat (C-10, «planificat») i el risc R-07 parla de «serveis oblidats» sense que ningú sàpiga quants n'hi ha avui. Aquesta lliçó converteix aquestes afirmacions en mesuraments: aprendràs a trobar què està exposat, decidir què s'arregla primer i demostrar que s'ha arreglat, amb eines de cost zero que caben al pressupost de Nimbus.

⚠️ Advertiment legal i d'autorització — llegeix-lo abans d'executar res

Tot el que hi ha en aquesta lliçó s'executa exclusivament sobre sistemes propis o amb autorització escrita, explícita i vigent.

  • Escanejar ports o llançar un escàner de vulnerabilitats contra una màquina aliena sense autorització pot constituir delicte a Espanya (arts. 197 bis i 264 del Codi Penal). La curiositat no és una eximent.
  • Al núvol has de complir a més la política de proves del proveïdor, i si el sistema l'opera un tercer —la consultora d'A-19, el proveïdor de correu, la passarel·la—, l'autorització ve de qui l'opera, no només de qui el contracta.

Tot el material treballa sobre el rang propi de Nimbus (10.20.0.0/16 a l'oficina, 10.30.0.0/16 al núvol) i el seu domini nimbusreservas.example. No hi ha exploits ni payloads: cada troballa va amb la seva correcció. (La interpretació penal concreta depèn del cas; davant d'una prova amb impacte sobre tercers, consulta assessoria jurídica.)

Contingut

  1. La gestió de vulnerabilitats com a procés continu
  2. El mapa d'eines: què troba cada família
  3. Descobriment de xarxa amb nmap
  4. Escàner de vulnerabilitats: Greenbone/OpenVAS
  5. Dependències i contenidors: pip-audit i trivy
  6. Anàlisi estàtica de codi i escaneig de secrets
  7. Priorització: CVSS, EPSS, KEV i exposició
  8. Falsos positius, falsos negatius i validació
  9. Integració al cicle i mètriques del procés
  10. L'informe de vulnerabilitats

  1. La gestió de vulnerabilitats com a procés continu

Gairebé totes les pimes que «fan gestió de vulnerabilitats» fan en realitat escaneig puntual: un cop l'any algú llança una eina, exporta un PDF de 300 pàgines i l'arxiva. Això no redueix el risc: genera un document. La diferència és un cicle tancat amb verificació.

flowchart LR
    I["0. INVENTARI\nQue tinc (A-01..A-22).\nSense aixo no hi ha cobertura"] --> D["1. DESCOBRIR\nnmap, escaner, SCA,\nSAST, secrets, cloud"]
    D --> P["2. PRIORITZAR\nCVSS + EPSS + KEV\n+ exposicio + criticitat"]
    P --> R["3. ESMENAR\nPedac, configuracio,\nmitigacio o acceptacio"]
    R --> V["4. VERIFICAR\nReescanejar i TANCAR\namb evidencia"]
    V --> N["5. INFORMAR\nMetriques i tendencia\n(KPI de 04-03)"]
    N --> D
    V -.->|"si no es corregeix"| E["EXCEPCIO amb caducitat\nal registre de riscos 04-01"]

Cinc regles separen el procés del teatre:

  • El pas 0 no és opcional. Un escaneig sobre 12 màquines quan en tens 18 no troba res a les altres 6: la cobertura és la primera mètrica, no l'última.
  • L'alimenten diverses eines, no una. Cap família no veu més del 30 % del problema.
  • Prioritzar no és ordenar per CVSS. És la part que més valor aporta i la que gairebé ningú no fa bé (§7).
  • Una troballa es tanca quan la nova passada d'escaneig ja no la troba, no quan algú diu que l'ha arreglada: aquesta és l'evidència auditable de 04-03. I el que no es corregeix es converteix en excepció amb caducitat (04-02), no en una fila que envelleix en silenci.

Precisió d'01-01: una versió d'OpenSSL amb CVE és una vulnerabilitat; que aquest servei escolti a Internet és l'exposició; el risc combina totes dues amb la criticitat de l'actiu. Una de crítica en una màquina apagada no és una urgència; una de mitjana a l'API pública que arriba a A-01 sí.


  1. El mapa d'eines: què troba cada família

Família Què troba / què no veu Lliures Comercial On
Descobriment de xarxa Hosts, ports, serveis i versions · no veu res dins de l'aplicació nmap, masscan Runzero, Censys §3 i 05-04
Escàner d'infraestructura CVE de sistema i serveis · no veu errors de negoci ni codi propi Greenbone/OpenVAS, Nuclei Nessus, Qualys §4
Escàner web dinàmic (DAST) Injeccions, XSS, capçaleres · no veu codi no assolible per la interfície OWASP ZAP, Nikto, testssl.sh Burp Pro, Invicti 05-05 i 05-03
Composició de programari (SCA) CVE en dependències · no veu errors al teu propi codi pip-audit, grype, osv-scanner Snyk, Mend §5
Anàlisi estàtica (SAST) Patrons insegurs al codi propi · no veu el que depèn de l'entorn semgrep, bandit, CodeQL Checkmarx, Fortify §6 i 05-05
Escàner de secrets · de contenidors Claus a l'historial de git · CVE de la imatge i males pràctiques del Dockerfile gitleaks · trivy, grype GitGuardian · Aqua §5-§6, 05-05 i 05-07
Configuració cloud i IaC Buckets públics, permisos excessius, xifratge absent · no veu l'aplicació prowler, ScoutSuite, checkov, tfsec Wiz, Orca 05-07
Configuració del sistema Desviació respecte d'una línia base CIS · no veu CVE d'aplicació lynis, OpenSCAP Tenable 05-06

La columna important és «què no veu». L'IDOR que Nimbus va corregir amb WHERE tenant_id no el troba cap d'aquestes famílies: no és una versió antiga ni un patró evident, és una fallada d'autorització que exigeix entendre el negoci. Per això l'escaneig es complementa amb revisió de codi (05-05) i proves manuals (05-03), i per això cap escàner no pot signar que un sistema és segur.


  1. Descobriment de xarxa amb nmap

nmap respon a la pregunta que Nimbus no sap contestar: què hi ha escoltant aquí fora i aquí dins?

# 1) Quines maquines estan vives a la VLAN d'usuaris de Valencia
sudo nmap -sn 10.20.10.0/24 -oA /var/log/nimbus-scan/oficina-hosts

# 2) Superficie completa de la VPC, executat DES DEL bastio
sudo nmap -sS -sV --version-intensity 5 -p- --max-retries 2 -T4 --open \
     -oA /var/log/nimbus-scan/vpc-intern 10.30.10.0/24 10.30.20.0/24 10.30.90.0/24

# 3) La mateixa infraestructura vista des d'INTERNET
nmap -Pn -sV --top-ports 1000 --reason -oA /var/log/nimbus-scan/extern \
     api.nimbusreservas.example preprod.nimbusreservas.example
Opció Què fa Per què importa aquí
-sn / -sS Descobrir hosts sense escanejar ports / SYN scan que no completa la connexió El primer es compara amb l'inventari d'01-04; el segon és ràpid i fiable, i requereix privilegis
-sV Interroga el servei per deduir producte i versió Converteix «5432 obert» en «PostgreSQL 14.7», que és el que es creua amb les CVE
-p- / --top-ports 1000 Els 65.535 ports / els més utilitzats El python -m http.server escoltava al 8000, fora del top 1000; però un -p- extern triga hores i es reserva per a la passada mensual
-Pn No comprovar si el host viu abans d'escanejar Obligatori des d'Internet: gairebé tot bloqueja ICMP i sense -Pn no trobaries res
-T4 Plantilla de temporització agressiva (0-5) Equilibri en xarxa pròpia; T5 perd precisió i T1-T2 són per no disparar deteccions
--reason / -oA Per què classifica així cada port / desa en els tres formats Distingeix «filtrat» de «tancat»; i sense la sortida anterior no hi ha diferencial, que és el 90 % del valor

Sortida real de l'escaneig extern:

Nmap scan report for preprod.nimbusreservas.example (203.0.113.47)
PORT     STATE    SERVICE    REASON   VERSION
22/tcp   open     ssh        syn-ack  OpenSSH 8.9p1 Ubuntu 3ubuntu0.1
443/tcp  open     ssl/http   syn-ack  nginx 1.18.0 (Ubuntu)
5432/tcp open     postgresql syn-ack  PostgreSQL DB 14.7 - 14.9
6379/tcp open     redis      syn-ack  Redis key-value store 6.0.16
8000/tcp open     http       syn-ack  SimpleHTTPServer 0.6 (Python 3.10.6)

Nmap scan report for api.nimbusreservas.example (203.0.113.20)
443/tcp  open     ssl/http   syn-ack  nginx 1.24.0
22/tcp   filtered ssh        no-response

Les troballes d'01-04, ara mesurades i amb data: 5432 accessible des d'Internet confirma R-03 (només el protegeix una contrasenya); 6379 amb Redis sense autenticació és R-07; 8000 és el python -m http.server oblidat durant 94 dies; i el contrast entre 22/tcp open a preproducció i filtered a producció demostra que a producció sí que hi ha una regla i a preproducció no. A-22 és avui el baula més feble de Nimbus.

Calen els dos punts de vista i mesuren coses diferents. L'extern (mensual automatitzat, control C-10) mesura la superfície que veu un atacant d'Internet, és a dir, l'exposició. L'intern (trimestral, des del bastió i des de la VLAN d'usuaris) mesura el que abasta qui ja és dins o un portàtil compromès, i per tant revela fallades de segmentació i moviment lateral: és el que hauria descobert, abans de l'incident, que des de la xarxa d'administració s'arribava a la zona de dades sense control intermedi (dia 1-4 de 02-06).


  1. Escàner de vulnerabilitats: Greenbone/OpenVAS

nmap diu què hi ha; l'escàner diu què li passa al que hi ha. Greenbone Community Edition (l'antic OpenVAS) és gratuït i suficient per a Nimbus. Només fa dues coses, i convé no atribuir-li màgia:

  1. Comparar versions contra una base de vulnerabilitats. És ràpid i és la font de gairebé tots els falsos positius: les distribucions apliquen pedaços sense apujar el número visible (backporting).
  2. Comprovacions actives: envia una petició i observa la resposta —si accepta TLS 1.0, si un tauler respon amb credencials per omissió—. Més lent i molt més fiable.
# Definir objectiu i tasca, i llancar-la; tot automatitzable des de cron
gvm-cli socket --xml '<create_target><name>VPC produccio</name>
  <hosts>10.30.10.0/24,10.30.20.0/24</hosts></create_target>'
gvm-cli socket --xml '<create_task><name>Mensual autenticat</name>
  <config id="daba56c8-73ec-11df-a475-002264764cea"/><target id="TARGET_ID"/></create_task>'
gvm-cli socket --xml '<start_task task_id="TASK_ID"/>'

El config id és la plantilla d'escaneig (Full and fast equilibra cobertura i temps). Un escàner que s'ha de llançar a mà es llança dues vegades l'any: es programa o no existeix.

Autenticat davant de no autenticat

No autenticat Autenticat
Com funciona Sondeja des de fora i dedueix Entra per SSH i llegeix el sistema per dins
Què veu Serveis exposats i els seus banners Tots els paquets, pedaços, configuració, usuaris
Troballes per servidor Linux 8-15 60-150
Falsos positius Molts (per backporting) Pocs: compara la versió real del paquet
Risc Cap La credencial de l'escàner és un actiu crític

Troba molt més perquè deixa d'endevinar: sense credencials no veu una biblioteca vulnerable que no escolta en cap port, i la majoria de les vulnerabilitats del sistema són exactament això. Per a Nimbus: compte svc-scanner sense sudo, clau Ed25519 dedicada (03-06), origen restringit i rotació semestral.

== Informe Greenbone · Escaneig mensual autenticat · 2026-04-06 ==
6 hosts analitzats · 1h42m · 3 Alt · 11 Mitja · 24 Baix · 63 Log

[10.0] 10.30.90.7   Redis sense autenticacio accessible a la xarxa
       Comprovacio ACTIVA: s'ha executat INFO sense credencials    QoD 99%
       Solucio: requirepass + bind 127.0.0.1 + grup de seguretat
[9.8]  10.30.20.5   PostgreSQL accessible des de 0.0.0.0/0
       Comprovacio ACTIVA: connexio establerta des d'origen extern QoD 98%
[7.5]  10.30.10.11  OpenSSL 3.0.2-0ubuntu1.9 - CVE-2026-1000
       Comprovacio de VERSIO del paquet (escaneig autenticat)      QoD 97%
[5.3]  10.30.10.11  nginx 1.18.0 - multiples CVE
       Comprovacio de VERSIO per banner remot                      QoD 30%
       ^-- baixa confianca: probable backport de la distribucio

Tres claus de lectura: QoD (Quality of Detection) és el camp més útil i el més ignorat —99 % amb comprovació activa és un fet, 30 % per banner és una hipòtesi, així que es comença per QoD alt i no per CVSS alt—; els 63 «Log» no són soroll, són inventari per a 01-04; i un informe sense troballes només significa que l'escàner no ha trobat res del que sap cercar: l'IDOR d'A-04 no hi apareixerà mai.


  1. Dependències i contenidors

El 80 % del codi que executa l'API no el va escriure l'Iván: són dependències. És la superfície que més creix i la més barata de mesurar.

pip-audit --requirement requirements.txt --format json --output /tmp/pip-audit.json --strict

--requirement audita les dependències fixades del projecte (sense ella audites la màquina) i --strict falla també si alguna cosa no s'ha pogut analitzar: tractar un «no ho sé» com un «està bé» és l'arrel dels falsos negatius.

Found 3 known vulnerabilities in 2 packages
Name      Version  ID                   Fix Versions
jinja2    3.1.2    GHSA-h5c8-rqwp-cp95  3.1.3
requests  2.28.1   GHSA-j8r2-6x86-q33q  2.31.0
requests  2.28.1   GHSA-9wx4-h78v-vm56  2.32.0

La de requests és la rellevant: l'API crida la passarel·la i el proveïdor de correu amb aquesta biblioteca. La de jinja2 només afecta plantilles del tauler intern. Mateixa severitat nominal, prioritat molt diferent.

trivy image --severity HIGH,CRITICAL --ignore-unfixed \
            --scanners vuln,secret,misconfig --format table \
            registry.nimbus.example/api:2026.04.1

--severity HIGH,CRITICAL filtra el soroll (una imatge base típica llança 300 troballes baixes, i incloure-les garanteix que no se'n miri cap); --ignore-unfixed amaga el que encara no té pedaç, i és l'opció més discutible —política de Nimbus: usar-la al CI per no bloquejar per una cosa irresoluble i no usar-la a l'informe mensual—; i --scanners vuln,secret,misconfig afegeix secrets a les capes i males pràctiques del Dockerfile: tres eines pel preu d'una.

registry.nimbus.example/api:2026.04.1 (debian 12.4)   Total: 14 (HIGH 12, CRITICAL 2)
┌───────────┬───────────────┬──────────┬───────────────┬──────────────┐
│ libssl3   │ CVE-2026-1000 │ CRITICAL │ 3.0.11-1      │ 3.0.13-1     │
│ zlib1g    │ CVE-2026-1001 │ HIGH     │ 1:1.2.13.dfsg │ 1:1.2.13-1+u1│
│ perl-base │ CVE-2026-1002 │ HIGH     │ 5.36.0-7      │ (no fixat)   │
└───────────┴───────────────┴──────────┴───────────────┴──────────────┘
Secret  api/.env.sample  AWS Access Key ID  (linia 4)   <-- revisar

Vulnerabilitat present ≠ vulnerabilitat explotable. perl-base és a la imatge perquè l'arrossega la base de Debian, però l'API no executa mai Perl: està present i no és abastable. Dos conceptes ho formalitzen:

  • Abastabilitat: hi ha un camí d'execució des del codi de Nimbus fins a la funció vulnerable? Analitzar-ho descarta fins al 70 % de les troballes.
  • VEX (Vulnerability Exploitability eXchange): document signat en què declares, per CVE i producte, si t'afecta (affected, not_affected, fixed, under_investigation) i per què.

Nimbus emet el seu VEX juntament amb l'SBOM de 04-04: quan una clínica pregunti per una CVE famosa, la resposta serà un document i no una trucada d'urgència. La resposta a una troballa no explotable no és ignorar-la, és documentar-la. I la via més eficaç per reduir-ne el nombre és canviar a una imatge base mínima o distroless (05-07), que elimina de cop el 80 % d'aquestes línies.


  1. Anàlisi estàtica de codi i escaneig de secrets

bandit -r app/ -ll -f json -o /tmp/bandit.json
semgrep --config=p/python --config=p/security-audit --sarif -o /tmp/semgrep.sarif app/

-ll limita a severitat mitjana o superior; --sarif produeix el format estàndard que GitHub mostra a la seva pestanya de seguretat. Troballa real al codi de Nimbus:

>> Issue: [B501:request_with_no_cert_validation] Requests call with verify=False
   Severity: High  Confidence: High  CWE-295  app/integrations/pasarela.py:44
# ABANS — el `verify=False` que va apareixer al modul 2. Desactiva la validacio
# del certificat: qualsevol a la ruta pot interposar-s'hi i llegir o alterar la
# peticio de pagament. TLS sense validacio no protegeix de res (03-05).
r = requests.post(URL_PASSARELA, json=payload, verify=False, timeout=10)

# DESPRES — validacio activa i confianca acotada de forma explicita.
r = requests.post(
    URL_PASSARELA,
    json=payload,
    verify="/etc/ssl/certs/ca-certificates.crt",  # cadena de confianca explicita
    timeout=(3.05, 10),                            # connexio i lectura per separat
)
r.raise_for_status()

El SAST encerta aquí perquè verify=False és un patró textual inequívoc, i falla amb l'IDOR perquè saber que hi falta WHERE tenant_id exigeix entendre el model de dades. Regla: troba errors de patró, no errors de raonament. A 05-05 escriuràs una regla semgrep pròpia que sí que detecta el patró concret de Nimbus.

gitleaks detect --source . --log-opts="--all" --report-format json --report-path /tmp/gitleaks.json

--log-opts="--all" és l'opció crítica: sense ella només mira l'arbre actual; amb ella recorre tots els commits i branques. Un secret esborrat l'endemà continua a l'historial i continua sent vàlid.

Finding:  DATABASE_URL=postgresql://nimbus_api:[email protected]:5432/nimbus
RuleID:   postgres-connection-string
File:     deploy/docker-compose.override.yml
Commit:   a91f3c7 (2024-11-02) Author: [email protected]

És el risc R-06 i l'escalada del dia 5 de 02-06. Correcció en aquest ordre: (1) rotar la credencial avui —està compromesa des del 2024 i esborrar el fitxer no la invalida; és el pas urgent i el que gairebé tothom posposa—; (2) moure-la al gestor de secrets (03-06); (3) reescriure l'historial amb git filter-repo, que és cosmètica comparada amb el pas 1; i (4) gitleaks com a hook de pre-commit i pas bloquejant del CI (control C-12).


  1. Priorització: CVSS, EPSS, KEV i exposició

Aquí el procés es guanya el sou. Un escaneig de Nimbus produeix ~180 troballes i la Lucía té 440 h/any per a tot. Ordenar per CVSS descendent és l'error més estès del sector.

Grup CVSS Què mesura Qui el calcula
Base Gravetat intrínseca i invariable El fabricant o el NVD (9.8 per execució remota sense autenticació)
Temporal (Amenaça a la v4) Si hi ha exploit públic i si hi ha pedaç S'actualitza amb el temps: 9.8 baixa a 8.5 sense exploit conegut
Ambiental El teu entorn: criticitat de l'actiu i controls presents Només tu: 9.8 en una màquina aïllada baixa a 4.0

El grup ambiental és el que converteix una llista genèrica en una llista teva, i l'únic que ningú no pot calcular per tu. S'hi sumen dos senyals externs:

  • EPSS (FIRST): probabilitat que una CVE sigui explotada els propers 30 dies, de 0 a 1, actualitzada diàriament. Més del 90 % de les CVE tenen EPSS < 0,05; una minoria concentra gairebé tota l'explotació real.
  • KEV (CISA): catàleg de vulnerabilitats amb explotació confirmada al món real. No és predicció, és un fet observat; la llista és curta i consultar-la és gratis.

Regla operativa de Nimbus: tot el que sigui a KEV i sigui accessible es tracta com a crític, tingui el CVSS que tingui. Una de 7.5 a KEV és més urgent que una de 9.8 amb EPSS 0,001.

Prioritat Criteri Termini
P0 Emergència A KEV i exposat a Internet, o compromís actiu 24 h, fora de finestra si cal
P1 Crítica CVSS ≥ 9.0 o EPSS ≥ 0,10 sobre actiu crític accessible 7 dies (coincideix amb C-16)
P2 Alta CVSS 7.0-8.9 sobre actiu crític, o KEV no exposat 30 dies
P3 Mitjana CVSS 4.0-6.9, o alta sobre actiu no crític 90 dies
P4 Baixa CVSS < 4.0 o no abastable (documentat a VEX) Cicle següent o excepció amb caducitat

Els terminis compten des del descobriment, no des de la publicació de la CVE. I si un P1 no arriba a termini no es reetiqueta a P2: s'obre una excepció signada (04-02). Rebaixar la prioritat perquè el quadre de comandament quedi verd és la forma més comuna de corrompre el procés.

"""Ordena troballes combinant gravetat, explotacio real i exposicio."""

TROBALLES = [   # id, cvss, epss, kev, exposat, actiu, criticitat(1-5)
    ("CVE-2026-1000",  9.8, 0.72,  True,  True,  "A-04 API",       5),
    ("CVE-2026-1002",  8.1, 0.004, False, False, "A-04 (perl)",    5),
    ("REDIS-SENSE-AUTH",10.0, 0.90, True, True,  "A-22 preprod",   2),
    ("CVE-2026-1010",  7.5, 0.31,  True,  False, "A-01 BD",        5),
    ("CVE-2026-1044",  9.1, 0.002, False, False, "A-14 portatils", 3),
]

def prioritat(cvss, epss, kev, exposat, criticitat):
    base = cvss / 10.0                                   # 1) gravetat normalitzada
    explotacio = 1.0 if kev else min(1.0, epss * 3)      # 2) KEV es FET; EPSS, matis
    exposicio = 3.0 if exposat else 1.0                  # 3) abastable triplica urgencia
    importancia = criticitat / 5.0                       # 4) inventari de 01-04
    return round(base * (0.3 + 0.7 * explotacio) * exposicio * importancia, 3)

files = [(prioritat(c, e, k, x, cr), i, a) for i, c, e, k, x, a, cr in TROBALLES]
for p, ident, actiu in sorted(files, reverse=True):
    termini = "24 h" if p >= 2.0 else "7 dies" if p >= 1.0 else "30 dies" if p >= 0.4 else "90 dies"
    print(f"{p:>6}  {ident:<16} {actiu:<18} -> {termini}")
 2.940  CVE-2026-1000    A-04 API           -> 24 h
 2.250  CVE-2026-1010    A-01 BD            -> 24 h
 1.200  REDIS-SENSE-AUTH A-22 preprod       -> 7 dies
 0.257  CVE-2026-1002    A-04 (perl)        -> 90 dies
 0.230  CVE-2026-1044    A-14 portatils     -> 90 dies

El que revela el resultat: REDIS-SENSE-AUTH té el CVSS més alt (10.0) i cau al tercer lloc per viure en un actiu de criticitat 2; CVE-2026-1044 té 9.1 —més que la 1010, de 7.5— i queda l'última perquè ni és a KEV, ni és abastable, ni afecta un actiu crític. Ordenar per CVSS hauria posat la Lucía a treballar tres dies en les dues vulnerabilitats menys urgents. Avís honest: que A-22 tingui criticitat 2 és la classificació documentada, i l'inventari admet que està «a revisar». Si preproducció té còpia de dades reals, la seva criticitat és 5 i el Redis puja al primer lloc: revisar aquella cel·la és més rendible que qualsevol escaneig.


  1. Falsos positius, falsos negatius i validació

Definició Cost Exemple a Nimbus
Fals positiu Reporta una cosa que no existeix o no s'aplica Temps i pèrdua de credibilitat del procés nginx 1.18.0 marcat malgrat el backport d'Ubuntu
Fals negatiu No reporta una cosa que sí que existeix Risc real no gestionat L'IDOR, que cap escàner no va detectar

Validació d'una troballa, en ordre de cost: (1) comprovar la versió real del paquet (dpkg -l | grep nginx) resol el 60 % dels falsos positius d'infraestructura; (2) llegir l'avís de la distribució (USN d'Ubuntu, DSA de Debian), que diu si aquella versió ja està corregida; (3) comprovar l'abastabilitat; (4) reproduir de forma no destructiva només si persisteix el dubte —verificar que un port respon o que falta una capçalera, mai explotar en producció: aquesta conversa és de 05-03—; i (5) documentar la decisió, apta o no, perquè un fals positiu tancat sense registrar reapareix cada mes i costa el mateix cada vegada.

Un escàner no substitueix mai el criteri. No sap que A-01 conté historials que revelen informació de salut, ni que A-19 té accés permanent, ni que preproducció potser té dades reals, ni pot trobar una fallada d'autorització. Mesura versions i configuracions: el risc el posa el context, i el context el posa una persona. Això s'escriu a la declaració de limitacions de l'informe (§10).


  1. Integració al cicle i mètriques del procés

Moment Què s'executa Durada Bloqueja?
Cada pull request gitleaks, semgrep, pip-audit < 3 min Sí: secrets i crítiques noves
Cada desplegament trivy sobre la imatge final < 2 min Sí, segons llindar
Setmanal ZAP baseline contra preproducció (05-05) 20 min No: informa
Mensual (C-10) nmap extern + Greenbone autenticat + prowler (05-07) 2-4 h No: troballes amb propietari
Després de canvis d'infra. nmap extern diferencial 10 min No: alerta de port nou

L'últim és el més barat i el més infravalorat: comparar l'escaneig d'avui amb el d'ahir i avisar només del que és nou és el que hauria detectat el http.server el mateix dia, i no 94 dies després.

# .github/workflows/seguretat.yml
name: Analisi de seguretat
on:
  pull_request:
  push: { branches: [main] }
  schedule: [{ cron: "0 5 * * 1" }]   # dilluns: captura CVE noves SENSE canvis de codi
permissions: { contents: read, security-events: write }

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }      # historial COMPLET: sense aixo gitleaks no veu el passat

      - uses: gitleaks/gitleaks-action@v2   # BLOQUEJANT: un secret no es negocia mai

      - name: Dependencies Python
        run: |
          pip install pip-audit
          pip-audit -r requirements.txt --strict --format json -o pip-audit.json || true
          # `|| true` deixa que el llindar l'apliqui LA NOSTRA politica, no el binari
      - run: python ci/llindar.py pip-audit.json --fallar-si CRITICAL,HIGH-KEV

      - run: docker build -t nimbus/api:${{ github.sha }} .
      - uses: aquasecurity/trivy-action@master
        with:
          image-ref: nimbus/api:${{ github.sha }}   # la imatge d'AQUEST commit, no :latest
          severity: CRITICAL,HIGH
          ignore-unfixed: true        # no bloquejar pel que encara no te pedac
          exit-code: "1"              # 1 = build trencat si queda res per sobre del llindar
          format: sarif
          output: trivy.sarif
      - if: always()                  # publicar TAMBE quan el pas anterior falla
        uses: github/codeql-action/upload-sarif@v3
        with: { sarif_file: trivy.sarif }

El principi de disseny: bloquejar el que és accionable i informar del que no ho és. Un pipeline que trenca el build per troballes que ningú no pot corregir acaba desactivat en dues setmanes, i llavors no protegeix de res. I el criteri de fallada el decideix Nimbus (ci/llindar.py), no una eina que canvia de versió: externalitzar-lo és cedir el govern del risc.

Mètrica Tipus Objectiu Què revela en fallar
Cobertura de l'escaneig KPI 100 % Mira-la primer: la resta de mètriques menteixen si no és 100 %. És la que més sorpreses dona: sol revelar que el 30 % no cobert era preproducció
MTTR per prioritat KRI P1 ≤ 7 d · P2 ≤ 30 d Capacitat insuficient o procés d'aplicació de pedaços trencat
Crítiques obertes fora de termini KRI 0 És la xifra del comitè: si creix, cal invertir o acceptar formalment
Taxa de reobertura i % tancats amb nova passada d'escaneig KPI < 5 % · 100 % Es tanca sense verificar: «tancat» significa «algú va dir que sí»

  1. L'informe de vulnerabilitats

Destinatari Què necessita Extensió
Marta (direcció) Risc de negoci, tendència i quina decisió se li demana 1 pàgina: semàfor, 3 xifres, 1 petició
Lucía (sistemes) Què toca, en quina màquina, amb quina ordre i per a quan Taula ordenada per prioritat
Iván (desenvolupament) Fitxer, línia, correcció i prova de regressió Issues al repositori, no un PDF
Client o auditor (06-04) Que hi ha procés, cadència i evidència 1-2 pàgines sense detall explotable

Estructura de l'informe mensual: resum executiu, abast i limitacions, metodologia i versions de les eines, troballes prioritzades, tendència, tancats i verificats, i annex tècnic. Les limitacions són el que protegeix honestament el lector: diuen què no es va escanejar i quines fallades aquestes eines no troben.

### VUL-2026-014 · PostgreSQL de produccio accessible des d'Internet

- **Prioritat:** P0 (KEV no · CVSS 9.8 · **exposat** · actiu A-01, criticitat 5)
- **Actiu:** `db-prod-1` (10.30.20.5) · **Risc associat:** R-03 (04-01)
- **Descobert:** 2026-04-06, escaneig extern mensual (C-10) · **Termini:** 2026-04-07

**Descripcio.** El grup de seguretat permet 5432/tcp des de `0.0.0.0/0`. Qualsevol
equip d'Internet pot intentar autenticar-se; l'unica proteccio es la contrasenya
del rol `nimbus_api`, sense limit d'intents.

**Evidencia.**
    $ nmap -Pn -p 5432 -sV 203.0.113.47
    5432/tcp open postgresql PostgreSQL DB 14.7 - 14.9   (syn-ack)

**Impacte en el negoci.** Acces a les dades de 40 cliniques, inclosos historials
que revelen indirectament informacio de salut. Equival al dia 5 de 02-06. Bretxa
notificable sota RGPD (06-03).

**Correccio.** Restringir la regla d'entrada a `10.30.10.0/24`. Sense finestra de
manteniment: l'API connecta per la ruta interna. **Esforc: 20 minuts.**
**Verificacio.** Nova passada d'escaneig extern del 5432; estat esperat `filtered`,
mes prova de fum de l'API. **Propietari:** Lucia · **Estat:** Obert

Els cinc elements que converteixen una troballa en accionable: evidència reproduïble, impacte de negoci i no només tècnic, correcció concreta amb esforç estimat, criteri de verificació explícit i un propietari amb nom. L'error més freqüent és lliurar el bolcat de l'eina: 300 pàgines sense prioritzar que garanteixen que no es corregeixi res, perquè ningú no sap per on començar.


Errors Comuns i Consells

  • Escanejar un cop l'any i dir-ne gestió de vulnerabilitats. L'inventari canvia cada setmana; millor mensual, automatitzat i revisat.
  • Ordenar per CVSS i començar per dalt. Sense exposició, EPSS/KEV i criticitat de l'actiu dedicaràs el temps al que menys importa. És l'error més car de la lliçó.
  • Escanejar sense credencials «per no molestar». Perds entre el 70 i el 85 % de les troballes del sistema; l'escaneig autenticat és la millora individual més rendible.
  • Oblidar preproducció. A-22 té avui més ports oberts que producció. L'atacant no distingeix entorns: distingeix portes.
  • Bloquejar el CI amb llindars impossibles, o tancar troballes sense verificar. El primer acaba amb el pipeline desactivat; el segon converteix «tancat» en «algú va dir que sí». Vigila la taxa de reobertura.
  • Consell: comença pel diferencial. Abans de muntar Greenbone, automatitza un nmap extern setmanal que compari amb l'anterior i desa sempre la sortida crua amb data (-oA, JSON, SARIF): és la teva sèrie històrica, i sense tendència no hi ha conversa amb direcció. Mitja hora de feina que hauria evitat dues de les quatre troballes d'01-04.
  • Consell: si només recordes una regla, que sigui aquesta. Una CVE a KEV i exposada es tracta avui.

Exercicis

Exercici 1 — Interpretar un escaneig i decidir l'ordre de treball

La Lucía llança el primer escaneig extern mensual i obté:

Nmap scan report for pruebas-2019.nimbusreservas.example (203.0.113.61)
80/tcp   open  http     Apache httpd 2.4.29 ((Ubuntu))
443/tcp  open  ssl/http Apache httpd 2.4.29
3306/tcp open  mysql    MySQL 5.7.33
  1. Què cal esbrinar sobre pruebas-2019 abans fins i tot de mirar les versions?
  2. Ordena les accions de la primera setmana justificant l'ordre amb els criteris de §7.
  3. Què li falta a aquest escaneig perquè el procés sigui complet?

Exercici 2 — Prioritzar cinc troballes

Ordena i assigna termini segons la política de §7, justificant cada decisió:

# Troballa CVSS EPSS KEV Exposat Actiu
A RCE en biblioteca d'imatges del tauler intern 9.8 0.02 No No A-04 (crític)
B Redis sense autenticació a preproducció 10.0 0.90 A-22 (a revisar)
C TLS 1.0 en un subdomini de màrqueting 5.3 0.01 No Web estàtica
D Credencial de PostgreSQL a l'historial de git des del 2024 A-10, A-01
E Escalada local al kernel dels portàtils 7.8 0.15 No A-14

Exercici 3 — Corregir un pipeline

Identifica almenys cinc problemes a la proposta de l'Iván i explica com es corregeix cadascun.

name: seguretat
on: { workflow_dispatch: {} }
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: gitleaks detect --source .
      - run: trivy image nimbus/api:latest --exit-code 1
      - run: pip-audit

Solucions

Exercici 1

(1) La primera pregunta no és tècnica, és d'inventari: què és pruebas-2019, qui el va posar, quines dades conté i encara cal? Aquest nom suggereix un entorn de fa set anys que ningú no manté i que no és a l'inventari d'01-04 ni a l'abast de cap aplicació de pedaços. Si ningú no ho sap, la correcció no és aplicar-hi pedaços: és apagar-lo després de confirmar que res no en depèn, conservant-ne una còpia. Apagar és la correcció més barata, més ràpida i més definitiva que existeix, i la que menys es considera.

(2) Ordre de la primera setmana:

  1. MySQL 3306 exposat (P0, 24 h). És el patró de R-03 però pitjor: base de dades accessible des d'Internet en un host sense manteniment des del 2019, amb credencials probablement febles. Es tanca al tallafoc avui, abans d'investigar res.
  2. Determinar si conté dades personals reals (P0, en paral·lel). Si en conté i feia anys que estava exposat, deixa de ser una troballa tècnica: és una possible bretxa amb obligacions del RGPD (06-03) i activació del pla de 04-05.
  3. Apagar el host (P1, 7 dies) un cop confirmat que res no en depèn. Apache 2.4.29 acumula anys de CVE: aplicar-hi pedaços és invertir en una cosa que ha de desaparèixer.
  4. Afegir-lo a l'inventari i revisar el DNS cercant més subdominis oblidats: que aparegués en un escaneig i no a l'inventari significa que la cobertura no era del 100 %.

(3) Què falta: l'escaneig només mira els ports habituals de noms que algú recordava. Falten l'enumeració de subdominis des de la zona DNS, un -p- mensual (el http.server del 8000 no surt a --top-ports 1000), escaneig UDP bàsic, escaneig intern des de la VLAN d'usuaris i des de la VPC per mesurar la segmentació, i les capes que nmap no cobreix: escàner autenticat, SCA, SAST i configuració cloud. nmap és el 15 % del procés.

Exercici 2

Ordre # Prioritat Termini Justificació
1r D P0 24 h No té CVSS perquè no és una CVE, i és el més greu: una credencial vàlida de la base de dades crítica, exposada des del 2024. No cal explotar res, n'hi ha prou amb usar-la. És R-06 i el dia 5 de 02-06. Rotar avui; netejar l'historial pot esperar
2n B P0 24 h KEV + EPSS 0,90 + exposat: els tres factors al màxim. La baixa criticitat nominal d'A-22 no el rescata, perquè està «a revisar» i probablement comparteix xarxa o dades amb producció. Tancar el port són minuts
3r E P2 30 dies És a KEV, l'explotació és real, però és escalada local: exigeix que l'atacant ja sigui al portàtil. És el segon baula de la cadena, no el primer. S'agrupa amb l'aplicació gestionada de pedaços del parc (05-06)
4t A P2 30 dies 9.8 sobre actiu crític, però no exposat i EPSS 0,02. Aquí és on ordenar per CVSS falla: sembla la primera i és la quarta. Convé confirmar l'abastabilitat; si el tauler no processa imatges d'usuari, baixa a P3 i es documenta a VEX
C P3 90 dies Exposat però de baix impacte: web estàtica, sense dades ni sessions. Una línia d'nginx (03-05) al manteniment següent. Tractar-lo com a urgent «perquè surt en vermell» és justament l'error que la política evita

Observació transversal: els dos primers no requereixen pedaç, sinó un canvi de configuració i una rotació de credencial, tots dos gratuïts i de minuts. El més urgent gairebé mai no és el més car.

Exercici 3

  1. workflow_dispatch com a únic disparador: només s'executa a mà, és a dir, gairebé mai. Falten pull_request, push a main i un schedule que capturi CVE noves sense canvis de codi.
  2. checkout sense fetch-depth: 0: gitleaks només veu l'últim commit, així que els secrets de l'historial —el cas real de Nimbus— passen desapercebuts indefinidament.
  3. trivy image nimbus/api:latest: escaneja una etiqueta que no és la imatge que aquest canvi construeix. Es valida una imatge i se'n desplega una altra; cal construir i escanejar per SHA del commit.
  4. --exit-code 1 sense --severity: bloqueja amb qualsevol troballa, incloses les informatives i les que no tenen pedaç. Es desactivarà en dues setmanes.
  5. pip-audit sense -r requirements.txt: audita l'entorn del runner, no el projecte; pot passar en verd amb dependències vulnerables.
  6. No es publica cap resultat i no hi ha permissions explícites: sense SARIF ni artefactes no hi ha historial, tendència ni evidència per a 04-03, i el token opera amb més permisos dels necessaris, contra el mínim privilegi d'01-03.

La versió corregida és la de l'apartat 9, amb fetch-depth: 0, els tres disparadors, permissions acotades, llindar propi a ci/llindar.py, imatge etiquetada per SHA i publicació SARIF amb if: always().


Conclusió

Has convertit el «verificar» del mòdul 4 en un procés mesurable. Saps que la gestió de vulnerabilitats és un cicle —inventariar, descobrir, prioritzar, esmenar, verificar i informar— i no un PDF anual, i que el pas 0 mana: sense inventari no hi ha cobertura, i sense cobertura la resta de mètriques menteixen. Coneixes el mapa de les nou famílies d'eines i, sobretot, què no veu cap d'elles: l'IDOR de Nimbus no apareix en cap escàner, perquè aquestes eines detecten errors de patró i no errors de raonament.

Manegues nmap opció a opció i saps per què l'escaneig extern i l'intern mesuren coses diferents; amb ell has retrobat amb data i evidència les quatre troballes d'01-04. Saps què fa realment un escàner de vulnerabilitats, per què l'escaneig autenticat en troba entre cinc i deu vegades més, i a llegir un informe començant pel QoD. Amb pip-audit i trivy distingeixes vulnerabilitat present de vulnerabilitat explotable, amb l'abastabilitat i el document VEX com a forma correcta de dir «no ens afecta» sense perdre traçabilitat. Amb semgrep, bandit i gitleaks has tancat el verify=False i has trobat la credencial de PostgreSQL a l'historial, la correcció de la qual comença per rotar-la i no per esborrar el fitxer. I t'endus la part que separa un procés útil d'un full de càlcul inútil: prioritzar amb CVSS base/temporal/ambiental, EPSS com a probabilitat i KEV com a fet observat, la política de terminis P0-P4 i un càlcul que reordena la llista fins a deixar la CVE de 9.1 a l'últim lloc; validar falsos positius en cinc passos; integrar-ho tot en un pipeline que bloqueja el que és accionable i informa de la resta; i redactar una troballa accionable amb evidència, impacte de negoci, correcció estimada, verificació i propietari.

Però fixa't en el límit de tot l'anterior: aquest procés troba portes mal tancades; no veu ningú entrant-hi. Si demà un atacant fa servir la credencial de la consultora a les 22:14, cap escàner d'aquesta lliçó no se n'assabentarà: el port està legítimament obert i la credencial és vàlida. Aquest és el buit que va deixar vint dies de silenci a l'incident de 02-06 i que el catàleg de 04-03 reflecteix amb vuit controls detectius dels quals només dos estan implantats. A Tècniques de Monitoratge i Detecció (05-02) construïm per fi aquests controls: què registrar, on centralitzar-ho, com escriure deteccions que es disparin amb el que importa i callin amb el que no, i com reduir el temps de permanència de l'atacant de vint dies a un matí.

Curs de Fonaments de Seguretat Informàtica

Mòdul 1: Introducció a la Seguretat Informàtica

Mòdul 2: Ciberseguretat

Mòdul 3: Criptografia

Mòdul 4: Gestió de Riscos i Mesures de Protecció

Mòdul 5: Eines i Tècniques de Seguretat

Mòdul 6: Bones Pràctiques i Normatives

Mòdul 7: Projecte Final

© Copyright 2026. Tots els drets reservats