Le serveur openssh, implémentation libre du protocole SSH proposée à l’origine par Theo De Raadt pour OpenBSD, est à mon avis une pépite du logiciel libre. J’estime que c’est probablement le daemon qui est le plus sécurisé de mes serveurs Linux, loin devant le serveur web par exemple. Je m’intéresse néanmoins aux astuces permettant de limiter les risques et vulnérabilités sous Linux (Debian 9, raspbian pour Raspberry, …).

Mise en place de clés d’authentification

En théorie, la meilleure méthode d’authentification auprès d’un serveur SSH, c’est la clé générée avec une passphrase. Cela constitue une authentification à deux niveau avec un élément à posséder (la clé) et un élément à connaitre (la passphrase).

Les assaillants qui ne possèdent pas la clé sont directement rejetés, c’est l’idéal. Les attaques bruteforce sont contrecarrées.

Pour mettre en place une clé sur votre client SSH c’est assez simple avec la commande ssh-keygen.

Pour que le serveur SSH distant reconnaisse la clé présentée par le client, il faut lui communiquer. La commande ssh-copy-id permet d’ajouter automatiquement la clé dans serveur:~/.ssh/authorized_keys .

La tentative de connexion suivante de l’utilisateur user auprès de serveur permettra normalement l’utilisation de la clé. Pour le vérifier on peut utiliser le mode verbose.

Après cette vérification on pourra interdire l’utilisation du mot de passe simple auprès du serveur avec la directive  PasswordAuthentication no  dans le fichier de configuration coté serveur /etc/ssh/sshd_config.

Si vous mettez en place les clés d’authentification, vous vous mettez en excellente posture du point de vue de la sécurité. Les mesures qui suivent ne me semblent du coup pas obligatoires, juste conseillées si vous recherchez la protection maximale.

Sécuriser openssh

En pratique, l’utilisation du mot de passe est bien pratique. Cela fonctionne par défaut, aussi bien avec un client SSH Linux qu’avec une appli smartphone ou tablette. Le mot de passe est un procédé ancestral et universel très largement adopté.

Les mesures qui suivent permettent de sécuriser l’utilisation du protocole SSH même en utilisant l’authentification par mot de passe.

Emploi des bons algorithmes de chiffrement

Dans le cadre de cet article, je m’intéresse plus à l’administration systèmes et au bonnes pratiques de hardening SSH. La confidentialité des échanges dépend des algorithmes de chiffrement utilisés d’une part pour l’authentification, et d’autre part pour le cryptage des échanges lorsque la connexion est établie. Cet article décrit très bien les algorithmes à autoriser et à interdire.

Interdire root avec un mot de passe

Coté serveur, la directive PermitRootLogin no  permet d’empêcher que l’utilisateur root ne se logue par SSH, autant par clé que par mot de passe. Pour mettre en place cette interdiction seulement pour le mot de place on remplacera « no » par « prohibit-password ». C’est la configuration par défaut sur Debian.

Limiter le nombre de tentatives d’authentification par connexion

La directive MaxAuthTries <num>  permet de limiter le nombre d’invites d’authentification. Les tentatives comptabilisées concernent à la fois la clé et le mot de passe. Les clients SSH ont tendance à proposer leur clé en premier puis à se rabattre sur le mot de passe en cas d’échec, si bien que la valeur numérique renseignée doit être choisie en tenant compte de cela.

Timeout d’authentification

Le délai de fermeture de connexion en cas de mot de passe ou de passphrase non renseigné est configurable avec la directive LoginGraceTime.

Modification du port d’écoute

La modification des ports standards pour l’écoute des services est intéressante, car les attaques automatiques sont calibrées justement pour des systèmes standards. Peu d’assaillants essaieront d’attaquer un serveur SSH par le port 80 par exemple (réservé à HTTP) ou encore le port 12345. Par contre j’ai déjà remarqué des tentatives sur le port 222.

Pour changer le port d’écoute SSH on pourrait mettre en place une règle iptables, ou encore toucher à la directive Port 22  dans /etc/ssh/sshd_config. Des options particulières peuvent également être spécifiées au démarrage du service SSH grâce au fichier /etc/default/ssh  sous Debian.

Le client ssh devra être lancé avec l’option -p pour spécifier le port distant.

Limiter la connexion à seulement certains utilisateurs

La directive AllowUsers permet de spécifier la liste limitative des seuls utilisateurs pouvant se connecter. La directive DenyUsers permet d’en interdire. La syntaxe prend en compte les noms d’utilisateurs simples (mike) ainsi que les couples utilisateur-hôte (john@ip).

Chrooter les utilisateurs dans leurs répertoires respectifs

La directive ChrootDirectory %h  permet de chrooter les utilisateurs dans leurs répertoires utilisateurs respectifs tels que définis dans /etc/passwd. C’est ce même fichier qui spécifie l’emplacement du shell, emplacement relatif à la racine absolue du système de fichiers ou à la racine chroot.

C’est pourquoi vous aurez le message d’erreur suivant si vous ne prenez pas de précautions particulières avec une arborescence chroot suffisante (exécutables comme bash, certaines librairies, …).

Pour l’exécutable bash, on se rend compte avec la commande ldd que certaines librairies présentes dans /lib et /lib64 sont requises. On peut les monter comme ceci :

Mais le plus simple est encore de trouver un bash statique, c’est à dire ne nécessitant pas de librairies externes. Le paquet Debian bash-static est prévu pour cela.

Par ailleurs, openssh nous oblige à ce que les répertoires de chroot appartiennent à root. Par exemple le répertoire /home/user doit appartenir à root pour l’utiliser en tant que racine chroot. Sans cela, vous aurez le message d’erreur suivant lors de vos tentatives de connexion.

Et également dans auth.log :

Il est toujours bon de tester le bon fonctionnement du chroot en ligne de commande avant de le configurer sur openssh.

Sécuriser l’usage de SSH par les possibilités Linux

Les conseils qui suivent font appel aux possibilités du système d’exploitation, plus que du daemon SSH en lui-même.

Délai de pause après un échec d’authentification (PAM)

Je trouve intéressant d’obliger le client SSH à partienter après un échec d’authentification. Cela décourage rapidement les petits curieux qui voudraient tester une attaque par force brute.

A l’heure actuelle il n’existe pas de directive de configuration coté serveur. Cela ce joue en amont, par le PAM (pluggable authentification modules).

La ligne permettant cela est la suivante, que l’on peut renseigner dans /etc/pam.d/ssh.

Je trouve que la configuration de PAM n’est vraiement pas simple, et j’ai souvent tenté des modifications sans qu’elles prennent effet. L’ordre des lignes de conf est important. Sur Debian 9 il faut intercaler la ligne ci-dessus au-dessus de @include common-auth .

La valeur numérique est en milisecondes, donc ici 9 secondes.

Désactivation du login de certains utilisateurs

On peut refuser à un utilisateur de s’authentifier auprès du système (par SSH ou la console) en préfixant le hash du mot de passe par un point d’exclamation dans /etc/shadow . Exemple :

 

Emploi d’un shell restreint

Le shell proposé à l’utilisateur suite à sa connexion est spécifié dans /etc/passwd . On remarque souvent /bin/bash  comme shell par défaut. Le choix le plus restrictif est /bin/false  qui n’est pas un shell mais plutôt un non-shell, un « rien du tout ».

Pour pousser un peu le hardening dans certaines situations (exemple : tunnel SSH simple), je recommande de chrooter l’utilisateur dans une arborescence minimale, avec un shell minimal lui-aussi.

Bannissement des assaillants avec fail2ban

Les assaillants qui reviennent un peu trop souvent peuvent être bannis via iptables grâce à un programme de surveillance des logs comme fail2ban. Sur Debian, l’installation de fail2ban suffit à surveiller les échecs de connexion SSH.

 

.