In questo articolo
In breve
- Scansioniamo soltanto una toy app nella rete Docker del laboratorio: nessun indirizzo Internet e nessuna porta pubblicata sul computer.
- La prima scansione trova due porte aperte. L'identificazione dei servizi e una richiesta HTTP mostrano cosa risponde davvero.
- Un nome di servizio o una versione sono indizi: la presenza di una vulnerabilità richiede una verifica ulteriore.
- Spegniamo il listener diagnostico superfluo e ripetiamo lo stesso controllo, conservando i report prima e dopo.
Tre porte, una domanda precisa
Una riga verde nel terminale può farti correre troppo. Leggi open, riconosci un nome e hai già in mente l'exploit. Fermati su una domanda più interessante: che cosa hai dimostrato davvero?
Qui lavoriamo esclusivamente su una piccola applicazione originale, avviata sul tuo computer in una rete Docker isolata. Le daremo un servizio utile e uno superfluo; li osserveremo, spegneremo il secondo e controlleremo che il primo funzioni ancora. È un esercizio di enumerazione completo, con una modifica e una prova finale.
Il metodo viene da lontano. Hacker Journal n. 270, marzo/aprile 2023, pp. 36–39, separava la ricerca delle porte dall'identificazione dei servizi su Metasploitable3. Nel n. 279, ottobre/novembre 2024, p. 22, mostrava quanto fosse fuorviante attribuire un servizio soltanto dal numero della porta. Sono lezioni ancora utili. Gli ambienti Windows e i servizi vulnerabili di quelle esercitazioni restano invece bersagli storici: per provarli oggi occorre conservarne esplicitamente versioni e isolamento.
Accendi la palestra
Scarica i sorgenti del laboratorio, estrai l'archivio e apri un terminale nella cartella pentest-percorso. Servono Docker con Compose che supporti up --wait e una shell POSIX: Linux, macOS o WSL.
mkdir -p evidence
docker compose build strumenti
docker compose pull archivio
DIAGNOSTICS=1 docker compose up -d --wait archivio
docker compose ps
lab() { docker compose run --rm --no-deps --user "$(id -u):$(id -g)" strumenti "$@"; }
Il primo avvio scarica immagini e pacchetti. Il container archivio esegue l'app; strumenti contiene Nmap e curl. La funzione lab esegue un comando nel secondo container e lo elimina al termine. Usa l'utente dell'host per scrivere i report anche su Linux senza modificare i permessi della cartella. I file sotto /evidence rimangono nella cartella locale evidence. Docker documenta questo uso di compose run.
Controlla il file compose.yaml: non contiene ports, usa internal: true e monta il codice in sola lettura. I container comunicano nella rete del progetto, senza pubblicare servizi sul computer. L'isolamento di rete è descritto nella documentazione Compose. Il nome archivio viene risolto dentro questa rete; non sostituirlo con indirizzi esterni.
--wait aspetta che l'app risponda alla healthcheck. Se l'avvio fallisce, leggi docker compose logs archivio prima di interpretare una porta chiusa come risultato del test.
Prima passata: che cosa accetta connessioni?
lab nmap -sT -Pn -n -p 8080,8081,8090 --reason \
-oN /evidence/01-porte.txt archivio
-sT usa connessioni TCP ordinarie, senza richiedere pacchetti raw. -Pn salta la fase preliminare di discovery: conosciamo già il bersaglio. -n evita la risoluzione inversa dei nomi; il nome iniziale archivio viene comunque risolto. -p limita il controllo a tre porte. --reason espone il motivo della classificazione e -oN conserva il risultato leggibile. Riferimento Nmap sulla scansione connect.
Queste righe sono un estratto del test eseguito il 31 ottobre 2026, con Nmap 7.97 nel container:
PORT STATE SERVICE REASON
8080/tcp open http-proxy syn-ack
8081/tcp closed blackice-icecap conn-refused
8090/tcp open opsmessaging syn-ack
Abbiamo due listener raggiungibili e una porta che rifiuta la connessione. I nomi http-proxy e opsmessaging non dimostrano ancora quale programma stia girando: senza interrogazione del servizio, Nmap può usare associazioni convenzionali tra porte e protocolli.
Anche gli stati hanno un confine preciso. closed significa che da qui la porta è raggiungibile ma non accetta connessioni; filtered indica che le risposte non permettono di stabilire se sia aperta. Cambiare punto di osservazione o regole di rete può cambiare il risultato. Stati delle porte secondo Nmap.
Seconda passata: interroga il servizio
lab nmap -sT -sV --version-light -Pn -n -p 8080,8090 \
-oA /evidence/02-servizi archivio
-sV invia sonde per identificare il servizio; --version-light limita l'intensità del rilevamento. Nel test la parte utile dell'output era:
PORT STATE SERVICE VERSION
8080/tcp open http-proxy?
8090/tcp open http SimpleHTTPServer 0.6 (Python 3.13.18)
Sulla 8090 il protocollo ora è HTTP. Sulla 8080 rimane un punto interrogativo: l'app originale restituisce risposte che il database di fingerprint non riconosce completamente. L'output include anche il fingerprint non riconosciuto; non occorre inviarlo ad alcun servizio esterno per completare il laboratorio.
Questa incertezza è un risultato utile. La documentazione del rilevamento versioni spiega perché i servizi possono vivere su porte inattese e perché la risposta dipende da ciò che il server rivela. Una versione dichiarata richiede riscontro prima di associarle una vulnerabilità sfruttabile.
-oA produce i formati .nmap, .xml e .gnmap. Se in seguito automatizzi l'inventario, usa l'XML e verifica esplicitamente lo stato open: cercare soltanto la stringa /tcp può includere anche porte chiuse. Formati di output Nmap.
La prova passa da HTTP
lab curl -sS -i http://archivio:8080/health
lab curl -sS -I http://archivio:8090/
Il primo comando restituisce 200 OK, il banner Able2CodeLab/1.0 e questo corpo:
{"service": "archivio-lab", "status": "ok"}
Il secondo conferma il server HTTP diagnostico. Il codice scaricato mostra che espone soltanto una pagina fittizia. Abbiamo così collegato tre elementi: porta raggiungibile, protocollo osservato e funzione del processo. Il nome della porta, da solo, non ci aveva dato queste informazioni.
Evita di allargare l'esercizio con --script all: NSE comprende anche script intrusivi, di brute force e DoS. Scegliere uno script richiede leggerne comportamento e prerequisiti, come avverte lo stesso manuale NSE.
Spegni il superfluo, poi misura
DIAGNOSTICS=0 docker compose up -d --wait --force-recreate archivio
lab nmap -sT -Pn -n -p 8080,8081,8090 --reason \
-oN /evidence/03-retest.txt archivio
lab curl -sS http://archivio:8080/health
Nel retest reale, 8080 rimane open, 8081 rimane closed e 8090 diventa closed. La risposta di /health conferma che l'app utile è ancora disponibile. La correzione consiste nel disabilitare il listener: nasconderne il banner non avrebbe ottenuto lo stesso risultato.
Conserva comando, orario, bersaglio, risultato iniziale, modifica e risultato finale. Questo piccolo fascicolo di prove dice esattamente cosa è cambiato. Il suo limite è altrettanto chiaro: tre porte TCP da un punto della rete. Non abbiamo verificato UDP, altre porte o la sicurezza dell'applicazione.
Un report utile può dire: «Il servizio diagnostico HTTP sulla porta 8090 era raggiungibile dal container strumenti. La configurazione DIAGNOSTICS=0 ne ha impedito l'avvio; la stessa scansione lo rileva chiuso, mentre /health su 8080 continua a rispondere». Ogni frase corrisponde a un'osservazione. Un generico «server messo in sicurezza» andrebbe molto oltre le prove raccolte.
Chiudi il laboratorio, oppure passa all'app
docker compose --profile strumenti down --remove-orphans
Il comando rimuove container e rete di questo progetto; i report e le immagini restano. Nel laboratorio IDOR con due account riaccenderai la stessa app per una domanda diversa: un utente autenticato può leggere un documento che appartiene a qualcun altro?
Chi difende un servizio può applicare subito questa sequenza: inventario, verifica del comportamento, disattivazione di ciò che non serve, controllo dei log e retest. La porta necessaria rimane aperta; il lavoro successivo riguarda ciò che l'app permette di fare attraverso quella porta.
Domande frequenti
Devo installare Kali o Nmap sul computer?
No. Servono Docker con Compose e una shell Linux, macOS o WSL. Il container strumenti include Nmap e curl. La prima preparazione scarica immagini e pacchetti; il laboratorio funziona poi sulla propria rete Docker interna.
Perché Nmap mostra http-proxy anche se l'app non è un proxy?
Senza rilevamento del servizio, il nome può provenire dalla tabella delle porte note. Nel test anche il fingerprint di 8080 rimane incerto, indicato da un punto interrogativo. Una richiesta a /health conferma HTTP e il nome dichiarato dall'app.
Una porta open dimostra che il servizio è vulnerabile?
Dimostra che un'applicazione accetta connessioni da quel punto della rete. Per stabilire una vulnerabilità servono altri elementi: comportamento, configurazione, versione effettiva e condizioni necessarie al difetto.
Il risultato comprende anche UDP e tutte le porte TCP?
No. Questo esercizio controlla soltanto TCP 8080, 8081 e 8090. Non autorizza conclusioni sulle altre porte, su UDP o sulla raggiungibilità da reti diverse.
Perché non riesco ad aprire archivio:8080 nel browser dell'host?
Il nome archivio esiste nella rete Docker del laboratorio e non ci sono porte pubblicate sull'host. Usa la funzione lab per eseguire curl nel container strumenti. È una scelta intenzionale di isolamento.


