"Se ci sono due o più modi di fare una cosa,
e uno di questi modi può condurre a una catastrofe,
allora qualcuno la farà in quel modo.

(Edward Murphy)

Hardening di base di un sistema linux ovvero i vaneggiamenti di un sysadmin paranoico

Sab, 16/07/2011 - 00:00 -- arturu
Tux linux

Premesso che la sicurezza in modo assoluto non esiste, oggi affronteremo un argomento molto vasto e complesso l'hardening di un sistema linux, cioè come rendere più sicuro un sistema esposto sulla rete. In realtà non esiste una guida o "la guida" per mettere in sicurezza un sistema linux ma esistono delle regole per evitare che un sistema sia meno attaccabile. Inoltre, questa non vuole essere una guida esaustiva ma una specie di promemoria sulle operazioni da compiere appena installato un sistema linux. Questo promemoria sull'hardening di un sistema linux è destinato a persone che hanno un po' di esperienza su linux, particolari conoscenze o riti arcani non servono, basta conoscere un po' il sistema che si intende modificare e i concetti base di linux, comunque, se ricopiate paro paro i comandi senza ragionare rischiate di rendere inaccessibile il vostro sistema.

Le partizioni e il filesystem

Come tutti sanno la radice del filesystem può essere su un unica partizione oppure articolata con diversi punti di montaggio. Come da molte guide che si possono trovare in giro per la rete è ormai assodato che le directory /tmp , /var , /usr e /home vanno montate in partizioni separate.

  • Il punto di montaggio /tmp è pubblico, cioè tutti gli utenti devono avere la possibilità di scrivere, quindi, un aumento spropositato di questo punto di montaggio potrebbe mettere in crisi tutto il sistema se esso fosse su un'unica partizione. Non conviene montare questa partizione con l'opzione noexec poiché spesso alcuni software usano questa posizione per installare/aggiornare i pacchetti. Poi, se si è abbastanza paranoici come il sottoscritto, si può montare la partizione con l'opzione noexec, quando bisognerà fare manutenzione sul sistema /tmp verrà smontata e rimontata senza l'opzione noexec.
  • Il punto di montaggio /var è altrettanto importante per quanto riguarda la sicurezza del sistema, specialmente per la presenza di /var/log, in esso vengonono salvati i log di sistema e in caso di un attacco DOS o un brute force potrebbe aumentare a dismisura. Questa partizione si può montare tranquillamente con l'opzione noexec.
  • Il punto di montaggio /usr va montato in sola lettura, da smontare e rimontare in scrittura quando bisogna fare manutenzione al sistema.
  • Per il punto di montaggio /home è buona cosa usare una partizione separata, per una serie infinita di motivi, tra i quali vi è la necessità di montare la partizione con l'opzione noexec. Questo si fa per evitare che un utente possa caricare un eseguibile bacato con l'intento di sfruttare lo stesso eseguibile per ottenere i privilegi di amministratore tramite shellcode.

Già queste impostazioni garantiscono una buona sicurezza, poi se si è abbastanza paranoici si può pensare di togliere il bit SUID/SGID da molti eseguibili non strettamente necessari, dipende da sistema a sistema. In caso si utilizza un sistema virtuale in remoto si potrebbe anche utilizzare le quote per settare le dimensioni massime che devono avere le cartelle.
Se siete sysadmin molto paranoici come il sottoscritto, subito dopo l'installazione del sistema ci si può calcolare hash di alcuni file sensibili: grep, ls, ps, netstat ecc; infatti, essi sono i primi che un probabile un attaccante modifica per nascondersi nel sistema. Per questa operazione è meglio usare MD5 e SHA1 al posto di MD2 e MD4 che sono algoritmi già violati (teoricamente anche l'MD5 è violabile ma solo in determinate condizioni che non rientrano nel nostro caso). Logicamente ad ogni aggiornamento bisogna ricalcolare gli hash, ci si può costruire facilmente uno script che faccia questo.

Utenti

Per un servizio che è costantemente esposto sulla rete i nomi utente giocano un ruolo molto importante se non fondamentale. Da molti bruteforce subiti, sicuramente da parte di bot che scansionano la rete alla ricerca di sistemi vulnerabili, i nome utente più attaccati sono: root, admin, administrator, testing, spam, postgres, ftpuser, user, newsletter, fax, ftp, office, training, demo, oracle, master, contact, staff, sales, backup, info, test, marketing, smtp, bob, windows, webmaster, mysql, anonymous, guest, ecc., quindi di conseguenza utilizzare questi nome utente per i servizi non è un'idea molto buona, usare questi username si semplifica del 50% il compito di un eventuale attaccante.
Una buona soluzione è quella di utilizzare per i nome utente regole simili quelle delle passwords o quasi. Per esempio, all'utente Mario Rossi si potrebbe impostare un nome utente tipo "MarioRossi123z" oppure "mrossi56ScF" e così via. La stesso concetto si può estendere anche agli accessi ftp o mail se si fornisce un servizio di hosting o simili.
Vietare l'accesso ssh agli utenti e non permettere l'utilizzo di shell, altrimenti un utente malintenzionato potrebbe compilare o caricare un eseguibile con un bug costruito ad hoc e attraverso esso ottenere i privilegi di root. Impostando la partizione /home con noexec, vietando agli utenti l'utilizzo di shell e dei compilatori possiamo stare relativamente tranquilli.

Volendo essere paranoici ci si può costruire uno script che analizza ogni ora o mezzora i log di sistema e ad un tot numero di login falliti da parte di un ip metta in banlist lo stesso. Ci si può inventare un pò di tutto, basta un pò di fantasia.

Servizi

I servizi senza ombra di dubbio sono la via d'accesso dei nostri potenziali intrusi, dire che bisogna mantenere aggiornato il software è abbastanza scontato, quindi, la prima regola è un update di sicurezza giornaliero.
La scelta migliore che si possa fare è chiudere tutti i servizi che non ci servono e rinforzare quelli che offriamo. Come prima cosa eliminare totalmente telnet e simili, se per caso sono installati, ma ormai neanche nelle installazioni di default ci stanno sti servizi. Successivamente controlliamo quali servizi sono aperti digitando da terminale:

netstat -t -u -l

oppure se preferiamo il numero delle porte

netstat -t -u -l --numeric-ports

dovremmo ottenere un output simile a questo

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address      Foreign Addr  State
tcp        0      0 *:pop3s                *:*       LISTEN
tcp        0      0 *:mysql                *:*       LISTEN
tcp        0      0 *:pop3                 *:*       LISTEN
tcp        0      0 *:imap                 *:*       LISTEN
tcp        0      0 localhost.locald:domain*:*       LISTEN
tcp        0      0 *:smtp                 *:*       LISTEN
tcp        0      0 *:imaps                *:*       LISTEN
tcp        0      0 *:http                 *:*       LISTEN
tcp        0      0 *:domain               *:*       LISTEN
tcp        0      0 *:ftp                  *:*       LISTEN
tcp        0      0 *:https                *:*       LISTEN
tcp        0      0 *:ssh                  *:*       LISTEN
udp        0      0 localhost.locald:domain*:*
udp        0      0 localhost.locald:domain*:*
udp        0      0 *:36593                *:*
udp        0      0 *:domain               *:*

Vediamo dove intervenire

Mettere in sicurezza SSH

Come detto in precedenza solo gli admin o l'admin dovrebbe essere abilitato a questo accesso, gli altri utenti non devono poter accedere a questo servizio. Inoltre, molto importante è disabilitare l'accesso all'utente root, i privilegi di superutente verranno acquisiti dagli admin tramite il comando su.
Apriamo il file /etc/ssh/sshd_config con un editor, per disabilitare l'accesso a root, lasciare l'accesso solo ad alcuni utenti e vietare l'uso di password vuote, modificare come segue le seguenti linee

PermitRootLogin no
AllowUsers pincopallino, secondopinco
PermitEmptyPasswords no

Una buona idea è cambiare la porta predefinita del servizio e forzare l'utilizzo del protocolo 2

Port 65000
Protocol 2

eventualmente per impedire l'utilizzo di sftp commentare la riga

#Subsystem  sftp  /usr/libexec/openssh/sftp-server

eventualmente se si volesse modificare il banner di presentazione del servizio, prima bisogna de-commentare la seguente riga e successivamente impostare una path dove salvare un file di testo con il banner

#Banner /some/path

modificato tutto, bisogna riavviare il servizio sshd stando attenti a non fare alcun errore, se si opera in remoto si rischia di autoescludersi dal sistema.

In caso la paranoia si fa sentire, si può abilitare l'accesso a ssh soltanto in possesso di una chiave crittografica impostando nel file di configurazione

PubkeyAuthentication yes

successivamente bisognerà generare una chiave privata e una pubblica per ogni utente a cui si vuole dare l'accesso, maggiori informazioni su http://sial.org/howto/openssh/publickey-auth o http://www.openssh.com, l'accesso si effettua soltanto con la chiave e non verrà richiesta alcuna password.
Inoltre, possiamo fare in modo che ogni utente loggato lavori in un abiente simile ad un sistema linux ma limitato di alcuni comandi utilizzando un fake chroot, oppure, possiamo prevedere l'apertura della porta ssh con il port knocking (la classica bussata segreta) per queste e altre tecniche rimando sempre al sito ufficiale di openssh, altrimenti questo articolo diventerebbe troppo lungo.

Gli altri servizi

Secondo il mio punto di vista sono da prediligere pop3s, smtps e imaps e da chiudere pop3, smtp e imap a meno che non abbiate degli utenti che li utilizzano, in tal caso bisognerà costruire una specie di piano d'uscita da questi servizi obsoleti.

Limitare un SYN Flood

Questo era un attacco DOS molto comune alla fine del secolo scorso, le recenti impostazioni di rete tendono a limitare o annullare del tutto questo tipo di attacco. L'attacco tende a saturare le risorse di sistema, una descrizione dell'attacco la si può trovare su http://www.cert.org/advisories/CA-1996-21.html . Per limare ulteriolmente le impostazioni di sicurezza rispetto a quelle della vostra rete si possono utlizzare i SYN cookies, essi limitano il numero di richieste da parte di un singolo utente. Aprire il file /etc/sysctl.conf (è un file di configurazione del kernel) ed editare le seguenti linee

#Prevent SYN attack
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = xxx
net.ipv4.tcp_synack_retries = 2

e le successive linee per la protezione contro l’IP Spoofing

# Enable IP spoofing protection, turn on source route verification
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.lo.rp_filter = 1
net.ipv4.conf.eth0.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

poi se si desidera configurare la distribuzione come un firewall possiamo utilizzare la configurazione proposta da http://openskill.info/infobox.php?ID=1166

net.ipv4.ip_forward = 1
net.ipv4.ip_dynaddr = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1

net.ipv4.tcp_sack = 0
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_window_scaling = 0
net.ipv4.tcp_syn_retries = 3
net.ipv4.tcp_synack_retries = 3

net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.default.log_martians = 1

net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.log_martians = 1

kernel.printk = 1 4 1 7

##
net.ipv4.tcp_max_syn_backlog=1280
net.ipv4.conf.all.send_redirects=0
net.ipv4.conf.all.forwarding=0
net.ipv4.conf.all.mc_forwarding=0
net.ipv4.vs.timeout_timewait=60

Conclusioni

Secondo il mio punto di vista questo è il minimo sindacale per mettere in sicurezza il nostro sistema esposto ai rischi della rete. Certo l'hardening non finisce qua, anzi, questa è solo la punta dell'iceberg, è compito di ogni sistemista documentarsi e apprendere giorno per giorno nuove tecniche, anche tentando di violare i propri sistemi per saggiarne la sicurezza.

In rete si trovano numerosi script che ci aiutano in questo compito, magari in un prossimo futuro farò un articolo in merito.

Saluti