Fork me on GitHub

Hardening OpenSSH

OpenSSH è il sistema standard per aprire una command line su sistemi linux-unix remoti. Il file di configurazione che ne regola il comportamento è tipicamente sshd_config nella directory /etc/ssh.

Il servizio, sui sistemi con systemd si attiva e si rende permanente all'avvio con la seguente sisntassi di systemctl:

[[email protected] ~]$ sudo systemctl start sshd
[[email protected] ~]$ sudo systemctl enable sshd

Per impostazione predefnita sshd permette l'accesso a tutti gli utenti di sistema che abbiano una shell valida (esempio /bin/sh o /bin/bash e non /sbin/nologin).
Per regolare l'accesso a determinati utenti possono essere utilizzate le direttive AllowUsers o DenyUsers e PermitEmptyPasswords per impedire l'accesso agli utenti con password vuota, es:

AllowUsers useradm
DenyUsers paperino
PermitEmptyPasswords no

Sinceramente preferisco negare sempre l'accesso come utente root. Se sarete gli unici amministratori del server conviene utilizzare un username difficilmente enumerabile, a cui concedere i diritti opportuni, o la possibilità di scalare di privilegio con il comando sudo o su. La direttiva che impedisce il login all'utente root è la seguente:

PermitRootLogin no

Con le direttive ClientAliveInterval e ClientAliveCountMax potete configurare dei timeout impostando a piacere tempi e ripetizioni:

ClientAliveInterval 300
ClientAliveCountMax 3

Che significano che dopo 300 secondi di inattività nella shell conteggiata per 3 volte, quindi 15 min in totale l'utente viene sloggato.

Il demone OpenSSH ascolta sulla porta 22 tcp. Il consiglio di base è uello di spostare la porta di ascolto su qualcosa di non standard, se esponente il sevizio pubblicamente, in modo da non rientrare nell'insieme dei bersagli predefiniti oggetto della curiosità di qualche script kiddies di passaggio. A questo scopo valorizzare la direttiva Port con un numero a piacere più grande delle famose porte ben conosciute (maggiore di 1000 quindi e meno di 65535).

Prima di effettuare quasta modifica tenete in considerazione l'adeguamenteo delle regole del firewall e di selinux se è attivo.

Con la direttiva ListenAddress potete invece limitare l'ascolto del server ssh sull'ip dell'interfaccia che desiderate (in caso abbiate un server multihomed) ad esempio un ethernet in lan anziche una interfaccia sulla wan, es:

Port 1357
ListenAddress 192.168.1.5

per accedere userete ssh in questo modo:

[[email protected] ~] ssh [email protected] -p 1357

Se considerate noioso digitare l'utente o la porta potete specificare questi parametri in un opportuno file di configurazione nella directory .ssh/

[[email protected] ~] vi $HOME/.ssh/config
Host server
HostName 192.168.1.5
        User useradm
        Port 1357

userete connettervi con un semplice:

[[email protected] ~] ssh server

Esistono 2 versioni del protocollo ssh la v1 e la v2. OpenSSH risponde a richeste esplicite di connessione v1 per compatibilità. Questo protocollo è suscettibile di attacco mitm e se non necessario può essere disabilitato specificando nel file di configurazione che il demone deve rispondere alle sole richieste v2 con la direttiva:

Protocol 2

Fra le vetustà a cui forse è possibile rinunciare vi è la possibilita di ignorare le direttive dei files ~/.rhosts ed ~/.shosts che sono l'equivalente utente del file /etc/hosts.equiv gestito dall'amministratore del sistema. Creando questi files, l'utente può concedere l'accesso ad un server a chiunque, a prescindere dalle policy dell'amministratore.

Fra le caratteristiche probabilmente non desiderate, fatto salvo la necessita di configurazioni particolari, vi è la possibilità di ignorare anche l'autenticazione detta Host-Based, che consente a tutti gli utenti di un sistema di loggarsi su un altro opportunamente configurato, ove i soli username coincidano. Le direttive in questione sono: IgnoreRhosts ed HostbasedAuthentication es.:

IgnoreRhosts yes
HostbasedAuthentication no

Una nota sull'autenticazione va detta, OpenSSH consente l'uso dell'autenticazione mediante password, quindi la robustezza della stessa è determinante ai fini di un eventuale penetrazione post attacco a forza bruta. Consiglio password casuali di numeri lettere e caratteri speciali superiori ai 16 o più caratteri per stare tranquilli (facili da memorizzare hahahah). In alternativa rinunziare del tutto alla password in favore di un autenticazione mediante chiave rsa.

Generate una coppia di chiavi rsa pubblica e privata sulla macchina client e copiate la parte pubblica sul server ed il gioco è fatto.

Se usate windows utilizzate PuTTYgen. Cliccate sul bottone Generate, muovete un pochino il mouse sull'area designata per generare un po di casualità, salvate la chiave pubblica e quella privata in una cartella a vostra scelta premendo su "Save public key" e poi su "Save private key". Mi sembra che il programma offra la possibilità di proteggere la chiave con una passprhase.

Su Linux è più facile, con il seguente comando generate la coppia di chiavi ed impostate la passprhase:

[[email protected] ~]$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user/.ssh/id_rsa.
Your public key has been saved in /home/user/.ssh/id_rsa.pub.
...

Una volta ottenute le chiavi copierete sul server a cui volete connettervi la vostra chiave pubblica nel file authorized_keys utilizzando un metodo di trasferimento sicuro (winscp ad esempio su windows), in questo modo:

[[email protected] .ssh]$ scp -P 1357 id_rsa.pub [email protected]:/home/useradm/.ssh/authorized_keys
[email protected]'s password:

Fate attenzione che la cartella remota (.ssh) nella home dell'utente remoto, in cui dovete copiare il file, esista. Fate attenzione che il file authorized_keys non esista già, in caso contrario appendete la vostra chiave a quelle esistenti invece di sovrascrivere il file.

La prossima volta che farete accesso sul server usando ssh non vi verrà richiesta la password dell'utente, bensì la passphrase delle chiavi rsa, es:

[[email protected] ~]$ ssh [email protected] -p 1357
Enter passphrase for key '/home/user/.ssh/id_rsa':
Last login: Tue Mar  3 21:36:33 2015 from host.client.it
[[email protected] ~]$

Sicuramente tutto questo lavoro è un passetto in avanti per risolvere il problema degli attacchi a forza bruta verso ssh, ma non risolve il problema di ricordarsi una lunga e noiosa passphrase della chiave rsa, ed il fatto di doverla ridigitare per ogni singola connessione. Come soluzione potrebbe venirci in mente di generare delle chiavi rsa senza passphrase ma ... no. Decisamente no, sarebbe proprio una cattiva idea. Infatti, un hacker che penetrasse il nostro sistema utilizzando un metodo non convenzionale per ottenere una shell, che so, da un applicativo vulnerabile che abbia generato un eccezione di qualche tipo, una volta fatto, avrebbe accesso trasparente ed indisturbato su qualunque server ove abbiamo copiato la nostra chiave pubblica.

Per evitare sia il problema di sicurezza che quello di essere annoiati tutte le volte dalla passphrase della chiave rsa, potete installare keychain un agente ssh che memorizzerà al login la/le passhprase per gli usi successivi per tutta la durata della sessione di lavoro.

Installiamo keychain con yum o apt-get, quindi adattiamo il nostro ambiente modificando il nostro file .bash_profile in questo modo:

[[email protected] ~]$ vi $HOME/.bash_profile
### START-Keychain ###
# Let  re-use ssh-agent and/or gpg-agent between logins
/usr/bin/keychain --clear $HOME/.ssh/id_rsa
source $HOME/.keychain/$HOSTNAME-sh
### End-Keychain ###

Salviamo il file, usciamo e rientriamo dalla sessione. Keychain ci chiederà la passphrase una tantum es.:

...
Last login: Tue Mar  3 22:39:14 2015 from 192.168.1.10

 * keychain 2.7.1 ~ https://www.funtoo.org
 * Found existing ssh-agent: 13888
 * Adding 1 ssh key(s): /home/user/.ssh/id_rsa
Enter passphrase for /home/user/.ssh/id_rsa:
 * ssh-add: Identities added: /home/user/.ssh/id_rsa

[[email protected] ~]$

Quando eseguiremo l'accesso al nostro server otteremo:

[[email protected] ~]$ ssh [email protected] -p 1357
Last login: Tue Mar  3 22:10:36 2015 from aaa.client.it
[[email protected] ~]$

ed il gioco è fatto.

Quando siete sicuri che potete accedere con la sola autenticazione a chiave pubblica, opportunamente protetta da passphrase, potete rimuovere l'autenticazione mediante password con la seguente direttiva:

PasswordAuthentication no

Per scremare la sorgente da cui è possibile accedere via ssh al nostro server, è possibile usare TCP Wrappers, che forniscono:

  • il supporto per Logging delle connessioni verso syslog
  • controllo degli accessi basato su pattern matching
  • verifica degli Host Name eseguendo reverse lookup dell'ip
  • protezione dallo Spoofing

per verificare se un programma è compilato per supportare TCP Wrappers, eseguire la seguente procedura:

[[email protected] ~]$ whereis sshd
sshd: /usr/sbin/sshd /usr/share/man/man8/sshd.8.gz
[[email protected] ~]$ ldd /usr/sbin/sshd | grep libwrap.so
        libwrap.so.0 => /lib64/libwrap.so.0 (0x00007f1945d08000)

se abbiamo almeno un output il demone supporta tcp wrappers.

per la configurazione, l'uso tipico prevede in /etc/hosts.allow:

sshd : /home/useradm/allowedIPS.txt

mentre in /etc/hosts.deny:

 sshd : ALL

Assicuratevi di avere già una shell attiva (od un accesso ad una console kvm) prima di sperimentare con tcp wrappers o vi taglierete fuori permanentemente.

Per generare dinamicamente il file allowed_ip.txt in caso utilizziate uno o più ip dinamici, vi consiglio questo stratagemma utilizzando un piccolo scriptino da eseguire in crontab:

[[email protected] ~]$ vi allowedIPS.sh
host1=`host miopc.ddns.org | awk '{print $4}'`
host2=`host miotelefono.noip.org | awk '{print $4}'`
echo "$host1
$host2" > /home/useradm/allowedIPS.txt

[[email protected] ~]$ crontab -e
*/30 * * * * /home/useradm/allowedIPS.sh

potete verificare il comportamento di TCP Wrappers con il comando tcpdmatch, ipotizzando che la connessione ssh provenga da microsoft.com oppure da un host autorizzato:

[[email protected] ~]$ tcpdmatch sshd  microsoft.com
client:   hostname grv.microsoft.com
client:   address  134.170.185.46
server:   process  sshd
access:   denied

client:   hostname microsoftproductionstudios.org
client:   address  134.170.188.221
server:   process  sshd
access:   denied

[[email protected] ~]$ tcpdmatch sshd host
client:   hostname ppp-1-5.2-1.tiscali.it
client:   address  1.5.2.1
server:   process  sshd
access:   granted

Commenti !

blogroll

social