Formati di output, gestione dei dati e flussi di lavoro di integrazione

I Formati di Output: Fondamenta Strutturali per il Consumo Programmatico

L'output di Nmap non è semplicemente telemetria leggibile dall'uomo—è un dato strutturato che determina se le tue scansioni si integrano pulitamente nelle operazioni di sicurezza o diventano oneri di parsing manuali. Tratta la selezione del formato come una decisione architetturale.

Formato normale (-oN) preserva la visualizzazione standard del terminale con commenti di runtime, tabelle delle porte e congetture sul SO. Rimane utile per investigazioni ad hoc e archivi di evidenza, ma non offre alcun percorso di parsing strutturato. Usalo solo per riferimento umano.

Formato XML (-oX) è la scelta canonica per le integrazioni. Si valida contro la Document Type Definition di Nmap e fornisce fedeltà completa della scansione. L'elemento radice <nmaprun> contiene figli <host>, ognuno con:

  • <address addr="..." addrtype="ipv4|ipv6|mac"/> per l'identificazione del livello di rete
  • <hostnames> con elementi <hostname> annidati per le associazioni DNS
  • <ports> contenente <port protocol="tcp|udp" portid="..."> con <state state="open|closed|filtered|unfiltered" reason="..."/> e figli opzionali <service name="..." product="..." version="..." extrainfo="..."/>
  • <os> con fingerprint <osmatch> classificati per accuratezza
  • <hostscript> per l'output NSE, annidato identicamente agli elementi <script> di <port>

La DTD XML garantisce una traversata prevedibile. Le query XPath estraggono intelligenze specifiche senza fragile matching di stringhe:

//host[ports/port[state/@state='open' and portid='22']]/address/@addr

Questo restituisce tutti gli IP con SSH accessibile. Per l'enumerazione dei servizi web:

//port[service/@name='http' or service/@name='https']/ancestor::host/address/@addr

Formato grepabile (-oG) presenta record delimitati da slash ottimizzati per pipeline di grep e awk. Tuttavia, è deprecato per le nuove integrazioni: tronca le stringhe di versione del servizio, omette completamente l'output degli script NSE, non può rappresentare indirizzi IPv6 in modo pulito e manca di annidamento gerarchico. Gli strumenti legacy potrebbero richiederlo, ma le pipeline moderne dovrebbero preferire XML.

Formato Script Kiddie (-oS) è un output novità in "l33t sp34k." Ha zero valore operativo.

Parsing Python e il Modello ad Oggetti XML

Per il parsing di produzione, python-libnmap astrae la DTD in oggetti interrogabili, oppure usa ElementTree per una gestione senza dipendenze:

import xml.etree.ElementTree as ET

def extract_vulnerable_hosts(xml_path):
    tree = ET.parse(xml_path)
    for host in tree.findall('.//host'):
        addr = host.find('address').get('addr')
        for port in host.findall('.//port'):
            portid = port.get('portid')
            state = port.find('state').get('state')
            service = port.find('service')
            if service is not None:
                name = service.get('name', 'unknown')
                version = service.get('version', '')
                # Logica di correlazione CVE qui
                if 'outdated' in version.lower():
                    yield {
                        'ip': addr,
                        'port': portid,
                        'service': name,
                        'version': version
                    }

Per repository di scansioni massicci, esegui il parsing in streaming con xml.iterparse per limitare il consumo di memoria.

Diffing delle Scansioni con ndiff: Rilevamento delle Modifiche su Scala

Le baseline di rete decadono immediatamente. ndiff confronta due output XML e produce delta strutturati:

ndiff baseline-scan.xml current-scan.xml > network-delta.txt

L'output usa + per le aggiunte, - per le rimozioni e intestazioni contestuali per le modifiche agli host. Critico per l'interpretazione SOC:

| Pattern | Significato di Sicurezza | |--------|----------------------| | + Nmap 7.94 scan initiated | Nuovo host apparso (dispositivo rogue, shadow IT) | | - 22/tcp open ssh | Servizio rimosso o filtrato (hardening o compromissione) | | + 8080/tcp open http Apache Tomcat 9.0.80 | Nuovo deployment di servizio (necessaria validazione patch) | | - 80/tcp open http + 443/tcp open ssl/http | Migrazione di servizio (verifica enforcement TLS) |

L'istituzione della baseline richiede scansioni rappresentative: flag identici, template di timing e condizioni di rete. Archivia le baseline nel controllo versione. L'alerting di rilevamento modifiche immette l'output di ndiff nei sistemi di monitoraggio—i codici di uscita non-zero segnalano deriva. L'analisi di regressione correla il timing dei delta con i ticket di change management; i delta inaspettati attivano la risposta agli incidenti.

I livelli di verbosità (-v, -vv, -d, -dd) richiedono ingegnerizzazione dei costi. Ogni incremento espande il volume dei log esponenzialmente. A -vvv, ogni decisione di timing dei pacchetti viene loggata—utile per il debugging, rovinosa per la retention. Standardizza: -v per le operazioni di routine, -d solo per l'investigazione dei fallimenti di scansione, con policy automatizzate di retention che stratificano i log grezzi nello storage cold.

Pipeline di Conversione e Trasformazione dei Dati

L'XML grezzo raramente alimenta direttamente le piattaforme di analisi. Tre percorsi di conversione dominano:

Trasformazioni xsltproc generano report HTML per il consumo esecutivo. Nmap include nmap.xsl:

xsltproc nmap.xsl scan.xml > report.html

Trasformate XSL personalizzate possono generare CSV, JSON o markdown per i sistemi di ticket.

python-libnmap esporta in JSON, CSV o SQLite direttamente:

from libnmap.parser import NmapParser
from libnmap.reportjson import ReportEncoder
import json

report = NmapParser.parse_fromfile('scan.xml')
json_output = json.dumps(report, cls=ReportEncoder)

Pipeline di ingestion nei database usando nmapdb o ETL personalizzati normalizzano i dati di scansione in schemi relazionali. Una tipica ingestion PostgreSQL:

CREATE TABLE scan_results (
    scan_id UUID,
    timestamp TIMESTAMPTZ,
    host_ip INET,
    port INT,
    protocol TEXT,
    state TEXT,
    service_name TEXT,
    service_version TEXT,
    os_match TEXT,
    nse_output JSONB
);

La colonna JSONB ospita output NSE estensibili senza migrazioni di schema.

Integrazione Metasploit: Dalla Scoperta all'Exploitation

Il comando db_nmap esegue Nmap con risultati automaticamente importati nel backend PostgreSQL di Metasploit:

msf6 > workspace -a client-engagement-2024
msf6 > db_nmap -sV -O --script vuln 10.0.0.0/24

L'isolamento dei workspace previene la cross-contaminazione tra engagement. Post-scansione, i comandi hosts, services, vulns e loot interrogano il database. La correlazione automatica degli exploit avviene tramite analyze:

msf6 > hosts -c address,os_flavor
msf6 > services -p 445 --rhosts
msf6 > vulns
msf6 > analyze

Il comando analyze abbina le voci vulns e le versioni services contro i moduli di exploit, classificandoli per affidabilità e compatibilità del target. Questo ciclo chiuso—dalla scoperta al suggerimento di exploit—comprime le timeline di ricognizione ma richiede una rigorosa validazione dello scope.

Architetture di Scansione Continua

Trasformare Nmap da strumento interattivo a infrastruttura di produzione richiede containerizzazione, scheduling e astrazione API.

L'esecuzione containerizzata garantisce ambienti riproducibili:

FROM alpine:latest
RUN apk add --no-cache nmap nmap-scripts
ENTRYPOINT ["nmap"]

Le configurazioni di scansione montano come ConfigMap; i risultati scrivono su volumi persistenti o object storage.

I CronJob di Kubernetes abilitano il discovery periodico con scheduling dichiarativo:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: network-discovery
spec:
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: nmap
            image: nmap:7.94
            command:
            - nmap
            - -sS
            - -p-
            - -oX
            - /results/scan-$(date +%Y%m%d).xml
            - 10.0.0.0/24
            volumeMounts:
            - name: results
              mountPath: /results
          restartPolicy: OnFailure

La visualizzazione Elastic Stack ingesta XML tramite parsing Logstash:

# Sezione filter di logstash.conf
xml {
  source => "message"
  target => "nmap"
  xpath => [
    "/nmaprun/host/address/@addr", "[nmap][host][ip]",
    "/nmaprun/host/ports/port/state/@state", "[nmap][port][state]"
  ]
}

Le dashboard Kibana tracciano le tendenze della superficie di attacco: conteggi delle porte aperte per sottorete, distribuzioni dell'età delle versioni di servizio, heatmap della scadenza dei certificati SSL.

I security gate CI/CD eseguono Nmap contro l'infrastruttura deployata prima della promozione. Fallisci le pipeline su servizi in ascolto inaspettati o divulgazioni di versioni proibite. Esempio GitHub Actions:

- name: Verify Staging Surface
  run: |
    nmap -sS -p 1-65535 -oX staging-scan.xml ${{ env.STAGING_IP }}
    python scripts/validate_baseline.py staging-scan.xml baselines/staging.xml

L'iniziazione di scansioni via API tramite wrapper REST (es. nmap-api, servizi Flask personalizzati) disaccoppia lo scheduling delle scansioni dall'esecuzione. I client POST specifiche di target; i worker accodano le scansioni, streammano i risultati tramite WebSocket e persistono sui backend. Questo pattern abilita piattaforme di scansione multi-tenant con accesso basato sui ruoli e logging di audit.

La progressione della maturità operativa passa dall'output basato su file (-oX su disco) attraverso la normalizzazione del database (Metasploit, PostgreSQL personalizzato) alle architetture basate su event-stream (topic Kafka per sottorete, rilevamento anomalie in tempo reale). Ad ogni stadio, la completezza strutturale della DTD XML previene la perdita di dati che la troncabilità grepabile o l'ambiguità del formato normale introdurrebbero.