Porte aperte: cosa guardare davvero
Quando si parla di porte aperte, la metafora della porta aiuta fino a un certo punto. In un sistema acceso non esiste una porta fisica: esistono socket, cioè estremi di comunicazione creati da un processo. Su TCP, il socket può essere messo in ascolto; su UDP non c'è un handshake e la verifica riguarda endpoint associati a una porta. Distinguere tra catalogo dei nomi, socket attivi e servizio che li governa evita due errori opposti: allarmarsi per ogni voce di un file di configurazione e ignorare un processo sconosciuto che ascolta su tutte le interfacce.
Il catalogo non è lo stato
Su Linux, /etc/services è un file ASCII che associa nomi leggibili a numeri di porta e protocolli. Una riga come ftp 21/tcp dice che il nome ftp
corrisponde alla porta 21 sul protocollo TCP; non dice che FTP sia
installato, avviato o raggiungibile. Il file è un dizionario consultato
dai programmi di rete, non un cruscotto dei processi attivi. Questo
punto viene spesso frainteso. La presenza di una voce in /etc/services
non implica che il servizio sia in esecuzione. Inoltre la politica IANA
tende ad assegnare sia TCP sia UDP quando assegna una porta, perciò
molte voci esistono in doppia copia anche per servizi che usano solo
TCP. Vedere una riga UDP nel catalogo non significa che ci sia qualcuno
in ascolto su UDP.
Un'altra distinzione utile riguarda i privilegi: su Linux e Unix i numeri di porta inferiori a 1024 possono essere associati solo da root. È un indizio sul livello di privilegio del processo, non una prova che il servizio sia legittimo o necessario. Anche un processo privilegiato può essere fuori posto.
Dove guardare: socket, non nomi
Per sapere cosa è realmente in ascolto bisogna interrogare il sistema operativo, non il file dei nomi. Su Linux, ss è uno strumento comune per elencare socket. L'opzione -t mostra TCP, -u UDP, -l i socket in ascolto, -p il processo proprietario e -n evita la risoluzione dei nomi.
# Elenca tutti i socket in ascolto (TCP e UDP) con processo e PID, senza risolvere i nomi sudo ss -tulpn
Per
vedere i PID dei processi di altri utenti servono privilegi adeguati;
senza di essi la colonna del processo può risultare incompleta. Il dato
importante non è solo la porta, ma anche l'indirizzo locale: un servizio
su 127.0.0.1:5432 ascolta solo in locale, mentre 0.0.0.0:5432 o [::]:5432 indica un ascolto su interfacce più ampie. La prima configurazione riduce l'esposizione, la seconda merita una domanda in più.
Su Windows si può partire da netstat -ano, che mostra endpoint e PID, oppure usare PowerShell per un elenco più leggibile.
# Socket TCP in ascolto: indirizzo, porta e PID proprietario Get-NetTCPConnection -State Listen | Select-Object LocalAddress,LocalPort,OwningProcess # Endpoint UDP: indirizzo, porta e PID proprietario Get-NetUDPEndpoint | Select-Object LocalAddress,LocalPort,OwningProcess
Il PID va poi ricondotto al processo e, quando esiste, al servizio che lo controlla. Un esempio di passaggio in PowerShell:
# Ricava il nome e il percorso dell'eseguibile a partire dal PID $procId = 1234 Get-Process -Id $procId | Select-Object Id,ProcessName,Path # Trova i servizi Windows ospitati da quel PID Get-CimInstance Win32_Service | Where-Object ProcessId -eq $procId | Select-Object Name,DisplayName,StartMode,State
Su Windows bisogna però fare attenzione a un dettaglio: molti servizi condividono lo stesso processo svchost.exe.
Un PID può quindi ospitare più servizi, e fermare il processo sarebbe
una scorciatoia sbagliata. Prima si identifica il servizio, poi si
decide se e come intervenire. Lo stesso vale su Linux quando un servizio
principale avvia processi figli o worker: il nome del processo non
coincide sempre con il nome dell'unità di sistema.

La domanda giusta non è "La porta è aperta?"
Una porta in ascolto non è automaticamente un problema. La domanda utile è: quel processo ha una ragione per ascoltare, su quell'indirizzo e con quel livello di privilegio? Per rispondere conviene costruire un inventario e confrontarlo con il ruolo della macchina.
Il servizio è previsto? Un server web, un database o un servizio di stampa possono essere normali su una macchina e fuori posto su un'altra.
Dove ascolta? Solo su loopback, su una rete interna o su tutte le interfacce? L'indirizzo di bind cambia molto l'esposizione.
Chi lo possiede? Un'unità di sistema, un servizio Windows, un container, un'applicazione avviata da un utente? Ogni caso richiede un controllo diverso.
Parte da solo? Sapere se il servizio è attivo ora non basta: conta anche se è abilitato all'avvio. Su Linux si distingue tra unità attiva e unità abilitata; su Windows tra stato corrente e modalità di avvio del servizio.
Da cosa dipende? Disabilitare un servizio senza conoscere le dipendenze può rompere funzioni non evidenti, come autenticazione, aggiornamenti o gestione remota.
Anche il firewall va tenuto separato dal processo. Una porta in ascolto può non essere raggiungibile dall'esterno perché il firewall la blocca o perché il servizio è legato solo a un'interfaccia locale. Viceversa, una regola firewall non chiude il processo: se il servizio non serve, va gestito sul sistema, non solo nascosto in rete.
Un caso concreto
Immagina che ss mostri un processo Python in ascolto su 0.0.0.0:8080.
Non è automaticamente un'intrusione: potrebbe essere un'applicazione
interna o un server di sviluppo. Se però è stato avviato da un utente e
ascolta su tutte le interfacce, il passo successivo è capire quale
applicazione sia, da quale directory parta e se quel tipo di esposizione
serva davvero. Un server di sviluppo può essere limitato a 127.0.0.1 o spento quando non serve; un'applicazione destinata alla rete interna va invece documentata e protetta.
Vediamo come farlo in pratica. Supponiamo che sudo ss -tulpn abbia restituito una riga simile a questa:
output
tcp LISTEN 0 128 0.0.0.0:8080 0.0.0.0:* users:(("python3",pid=4321,fd=3))Il PID è 4321. Da qui si procede per gradi.
# Identifica il processo: nome, utente proprietario e comando completo ps -fp 4321
Questo
mostra la riga di comando con cui è stato avviato il processo. Spesso è
già sufficiente a capire di cosa si tratta: per esempio python3 -m http.server 8080 è un server di sviluppo, non un servizio di produzione.
# Vedi la directory di lavoro e l'eseguibile reale del processo sudo ls -l /proc/4321/cwd /proc/4321/exe
cwd indica da quale directory è partito il processo, exe
l'eseguibile effettivo (utile se il nome del processo è stato alterato o
se è un interprete che esegue uno script). Per vedere l'intera riga di
comando con i separatori nulli, più affidabile di ps:
# Legge la riga di comando completa separando gli argomenti con spazi sudo tr '\0' ' ' < /proc/4321/cmdline; echo
# Controlla se il processo è governato da un'unità systemd o è stato avviato a mano systemctl status 4321
Se il processo appartiene a un'unità systemd, questo comando la mostra con stato e modalità di avvio. Se invece restituisce un errore del tipo "unit 4321.service could not be found", è probabile che sia stato avviato manualmente da un utente o da uno script, e non da un servizio di sistema: è un'informazione decisiva per capire se quell'ascolto è previsto.
# Conferma l'indirizzo di bind effettivo della porta 8080 sudo ss -tlnp 'sport = :8080'
Se compare 0.0.0.0:8080 o [::]:8080, il servizio è raggiungibile da altre macchine (salvo firewall); se compare 127.0.0.1:8080, l'ascolto è solo locale e l'esposizione è molto ridotta.
# Controlla il firewall, che è un livello separato dal processo sudo nft list ruleset # su sistemi con nftables sudo iptables -S # su sistemi con iptables
Questo serve a distinguere due situazioni diverse: un servizio esposto ma bloccato dal firewall, e un servizio realmente raggiungibile. Ricorda che una regola firewall non chiude il processo: se il servizio non serve, va gestito sul sistema.
Se dai passaggi precedenti emerge un server di sviluppo avviato a mano, per esempio un server python, la correzione tipica è riavviarlo legandolo solo al loopback:
# Riavvia il server di sviluppo in ascolto solo su localhost python3 -m http.server 8080 --bind 127.0.0.1
Se invece il processo risulta parte di un'applicazione destinata alla rete interna, non lo si spegne: lo si documenta (cosa fa, chi lo ha avviato, su quale interfaccia deve ascoltare, con quale unità o modalità di avvio) e lo si protegge con le regole firewall e i privilegi adeguati.
Su
Windows lo scenario equivalente può essere un processo sconosciuto con
un PID che, una volta interrogato, risulta associato a più servizi
dentro svchost.exe. In quel caso non
si chiude il processo: si elencano i servizi ospitati, si guarda la loro
modalità di avvio e si verifica quale funzione svolgono. Solo dopo si
decide se uno di essi è superfluo.
Prima di chiudere
AUTORE
Redazione ThreatHunting.it
Da piu' di 30 anni sono appassionato di computers e tecnologia. il mio primo programma lo sviluppai in Basic nel 1989, non era un gran che :).. ma quella voglia di scrivere codici non mi ha piu' lasciato …
COMMUNITY
Non ci sono ancora commenti. Puoi iniziare tu la conversazione.