Hardening: mettere in sicurezza il tuo server

Hardening: mettere in sicurezza un server

 

Per hardening di un server si intende il processo di miglioramento della sicurezza di un sistema per ridurre le sue vulnerabilità e quindi i rischi di attacchi. Questo processo prevede diverse pratiche di configurazione, soprattutto per i servizi essenziali, per minimizzare le vulnerabilità e aumentare la resistenza del server agli attacchi.

La guida che segue si concentra sulle principali attività di hardening per un server Linux (ad esempio Ubuntu o CentOS), ma molte delle pratiche possono essere applicate anche su altri sistemi operativi.

Inoltre, ogni passo di questa guida aiuta a ridurre i rischi di vulnerabilità, ma è essenziale rimanere aggiornati sulle ultime minacce e migliorare costantemente la sicurezza del sistema anche in base agli applicativi in uso.

È altresì importante assicurarsi di eseguire regolarmente audit di sicurezza, aggiornamenti e backup per mantenere il server protetto.

Di seguito le principali azioni consigliate:

Aggiornamenti e patch di sicurezza

Tra i fondamenti della sicurezza troviamo il mantenere un ambiente sempre aggiornato così da installare eventuali fix di sicurezza per bug noti.

È possibile impostare gli aggiornamenti automatici per l’intero sistema così da non dover procedere manualmente. Tuttavia, in ambienti di produzione può essere consigliabile verificare di volta in volta gli aggiornamenti disponibili prima di installarli, così da sapere cosa si va ad installare, facilitando anche eventuali azioni di troubleshooting post aggiornamento.

In linea generale, la regola fondamentale da tenere a mente è quella di installare solamente pacchetti di cui si ha realmente bisogno in quanto ogni applicativo presente sul server potrebbe essere una potenziale vulnerabilità.

Di seguito i comandi principali per verificare e installare gli aggiornamenti:

Ubuntu/Debian:

sudo apt update && sudo apt upgrade
sudo apt dist-upgrade
sudo apt autoremove

CentOS/RHEL:

sudo yum update
sudo yum autoremove

 

Gestione degli utenti e controllo accessi

Entrare in un server con utente root o con gli stessi privilegi non è assolutamente consigliato in quanto in caso di possibile compromissione anche i malintenzionati potrebbero avere pieno accesso alla macchina.

Per questo, si tende a disabilitare la possibilità di accedere come root anche se spesso si ha bisogno di avere gli stessi privilegi per effettuare determinate attività.

In questo caso possiamo creare una nuova utenza:

adduser [nome user] (Ubuntu/Debian)
useradd [nome user] (Red Hat/Centos)

per la quale andare a definire una password:

passwd [nome user]

In seguito è possibile aggiungere l’utenza appena creata nel gruppo sudo in modo da permettergli l’utilizzo dei privilegi di root quando necessario:

usermod -aG sudo [nome user]

Così facendo, si può accedere e autenticarsi con le credenziali di questa utenza nell’ambiente, per richiamare poi i comandi con i privilegi di root aggiungendo il sudo davanti ad ogni comando che lo richiede, esempio:

sudo adduser

Altro aspetto da controllare sono gli utenti che hanno accesso al sistema, verificabili con:

cat /etc/passwd

quindi è possibile rimuovere gli utenti che non sono più necessari:

sudo deluser nome_utente

Infine, controllare i permessi dei file e delle cartelle sensibili tramite il comando:

ls -l

e modificare i permessi se necessario.

In caso di file eseguibili, una buona abitudine potrebbe essere quella di fornire il permesso di esecuzione (+x) solo quando necessario e rimuoverlo una volta terminata l’attività.

 

Configurazione del firewall

Il firewall è una delle prime linee di difesa contro gli attacchi esterni. Per configurare un firewall su Linux è consigliabile utilizzare iptables o UFW configurando regole per consentire solamente il traffico necessario ai servizi in uso e bloccare quello indesiderato.
La maggior parte dei servizi principali, infatti, utilizzano porte di default che vanno aperte per un corretto funzionamento come ad esempio le porte 80 e 443 utilizzate dai protocolli http/https, quindi per rendere raggiungibili dall’esterno i siti web ospitati sulla macchina.
In termini di sicurezza solitamente si disabilita totalmente il traffico in ingresso tranne che per alcune specifiche porte necessarie. Quindi prima di tirare su le difese definiamo correttamente almeno la regola per poter accedere alla macchina in modo da non rimanere bloccati fuori dall’ambiente una volta chiuso il traffico in entrata.

In base alla tipologia di firewall in uso è possibile creare regole più o meno restrittive per abilitare/disabilitare il traffico su determinate porte o per specifici IP/classi di IP.

Di seguito un elenco dei comandi principali per la gestione del firewall tramite UFW o iptables:

UFW: Debian/Ubuntu

Attiva il firewall:
sudo ufw enable

Disattiva il firewall:
sudo ufw disable

Ripristina le regole di default, cancellando quelle esistenti:
sudo ufw reset

Blocca tutto il traffico in ingresso:
sudo ufw default deny incoming

Consente tutto il traffico in uscita:
sudo ufw default allow outgoing

Consente SSH (porta 22 TCP di default):
sudo ufw allow ssh

Consente HTTP (porta 80 TCP):
sudo ufw allow 80/tcp

Consente HTTPS (porta 443 TCP):
sudo ufw allow 443/tcp

Blocca la porta 23 (Telnet):
sudo ufw deny 23

Blocca la porta 23 solo in TCP:
sudo ufw deny 23/tcp

Consente DNS su UDP porta 53:
sudo ufw allow 53/udp

Consente tutto il traffico da IP specifico:
sudo ufw allow from 192.168.1.100

Consente SSH solo da subnet 192.168.1.0/24:
sudo ufw allow from 192.168.1.0/24 to any port 22

Blocca tutto il traffico da una subnet:
sudo ufw deny from 203.0.113.0/24

Consente traffico TCP per un range di porte:
sudo ufw allow 5000:5010/tcp

Visualizza regole in modo sintetico:
sudo ufw status

Visualizza regole con numerazione utile per cancellazioni:
sudo ufw status numbered

Rimuove una regola specifica:
sudo ufw delete allow 22/tcp

Rimuove la regola numero 3 (utilizzando numero da `status numbered`):
sudo ufw delete 3

Iptables: Red Hat/Centos

Abilitare il servizio iptables per l’avvio automatico:
sudo systemctl enable iptables
sudo systemctl start iptables

Mostra le regole attive con dettagli, pacchetti e byte conteggiati:
sudo iptables -L -v -n

Salvare le regole per renderle persistenti al riavvio:
sudo service iptables save

Blocca tutto il traffico in ingresso di default:
sudo iptables -P INPUT DROP

Consente tutto il traffico in uscita di default:
sudo iptables -P OUTPUT ACCEPT

Blocca traffico inoltrato di default:
sudo iptables -P FORWARD DROP

Consente traffico specifico ad es. SSH:
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

Consentire traffico su porta specifica ad es. HTTP (80):
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT

Bloccare traffico da IP specifico:
sudo iptables -A INPUT -s 192.168.1.10 -j DROP

Rimuovere una regola specifica(dopo averla trovata nella lista numerata, ad esempio la regola 3):
sudo iptables -D INPUT 3

Resettare tutte le regole iptables:
sudo iptables -F

Limitare il numero di connessioni simultanee (per esempio su porta 80):
sudo iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 10 -j REJECT

Si rimanda sempre alla man page dei relativi servizi (man ufw/man iptables) per avere una visione completa delle possibili personalizzazioni delle rules.

Disabilitare i servizi inutilizzati

I servizi presenti sul server ma non necessari possono essere una porta aperta per gli utenti non autorizzati. Procedi quindi a disabilitare tutti i servizi e i demoni non essenziali consentendo l’esecuzione solo di quei programmi di cui si necessita.

È possibile verificare quali servizi sono in esecuzione su quali porte tramite il comando:
netstat -npl

Inoltre, per i sistemi che eseguono systemd è possibile eseguire il comando:
systemctl list-units --type=service

per ottenere una lista di tutti i servizi in esecuzione.

Nel caso siano presenti servizi di cui non si ha bisogno è possibile disabilitarli tramite il comando:
sudo systemctl disable nome-servizio
sudo systemctl stop nome-servizio

Configurazione di SSH

SSH è uno dei punti più vulnerabili di un server, quindi è fondamentale configurarlo correttamente per evitare attacchi di tipo brute force.

Il file di configurazione da modificare si trova al path /etc/ssh/sshd_config e di seguito le modifiche consigliate:

Disabilitare il login come root tramite SSH impostando:
PermitRootLogin no

ricordarsi di verificare che sia stato già creato un altro utente con il quale si riesce correttamente ad accedere al sistema come detto in precedenza.

Personalizzare la porta in uso dal servizio SSH modificando la riga:
#Port 22

basterà rimuovere il commento alla riga cancellando # e modificare il numero della porta con quello desiderato.
Anche in questo caso è necessario fare attenzione che la porta che si va ad impostare sia abilitata in ingresso sul firewall al fine di evitare l’impossibilità di accedere alla macchina.

Disabilitare l’autenticazione con password modificando la relativa riga come segue:
PasswordAuthentication no

Disabilitando tale opzione sarà possibile utilizzare altri metodi di autenticazione, il consigliato tramite chiavi SSH.

Usa l’autenticazione tramite chiavi SSH anziché password come accennato in precedenza.

È necessario generare in precedenza una chiave SSH sul dispositivo locale tramite il comando:
ssh-keygen -t rsa -b 4096

Successivamente sarà necessario digitare la posizione del file in cui salvare la chiave privata. Non scrivendo niente verrà salvato nel path di default:
/home/$user/.ssh/id_rsa

La chiave pubblica sarà salvata nella stessa posizione, sotto lo stesso nome, ma con l’estensione .pub.
Verrà così generata una coppia di chiavi, una pubblica e una privata per l’utente.

In seguito copiare solo la chiave pubblica sul server:
ssh-copy-id user@server_ip

mentre la chiave privata rimane sul proprio dispositivo.

Poi, riavviare SSH per rendere effettive le modifiche apportate:
sudo systemctl restart sshd

Per una maggiore sicurezza occorre limitare gli accessi a SSH da indirizzi IP specifici tramite regole del firewall come spiegato precedentemente.

Backup e gestione dei log

I backup regolari sono essenziali per garantire il recupero dei dati in caso di attacco.

È consigliabile quindi eseguire backup regolari dei dati possibilmente salvati su servizi terzi rispetto il server per una migliore ridondanza dei dati.

Inoltre, la gestione dei log è importante per monitorare attività sospette. Per ogni servizio presente sul server è possibile configurare il path in cui trovare il file di log e anche la verbosità di scrittura, cioè il livello di dettaglio delle informazioni scritte nel file di log.

I livelli di verbosità che solitamente possono essere configurati sono:
TRACE (o DEBUG): informazioni dettagliate, passo passo, sull’esecuzione del codice.
INFO: messaggi informativi su operazioni normali, come l’avvio e la chiusura di servizi.
WARN: avvisi su situazioni non ottimali ma non critiche.
ERROR: segnalazioni di errori che richiedono attenzione.
FATAL (o CRITICAL): errori gravi che portano all’interruzione del sistema.

La scelta del livello di verbosità del logging è una decisione strategica che dipende dalle esigenze specifiche del sistema e dal contesto in cui viene utilizzato.
Prendendo ad esempio la navigazione di un sito web e i possibili log relativi alle attività del web server, un logging verboso potrebbe includere dettagli su ogni richiesta HTTP, ogni accesso al database e ogni operazione di file. Un logging meno verboso potrebbe limitarsi a registrare gli errori di autenticazione, gli errori SQL e gli accessi che hanno generato errori 500.