Sécuriser Secure Shell (SSH)

wallhaven-204494

Vous avez peut-être entendu dire que la NSA serait capable de décrypter SSH, ou en tout cas, sous certaines conditions. Si ce n’est pas le cas, je vous conseille de jeter un œil aux récentes informations dévoilées par Edward Snowden. Toutes. Pas de panique, ce billet sera toujours là lorsque vous aurez terminé. Mon objectif ici avec cet article est de rendre les analystes de la NSA… tristes.

Attention cet article risque d’être un peu long et technique. Si vous n’avez pas le temps, l’essentiel se cache dans les cadres avec une police à chasse fixe. Tous les snippets et les commandes y seront présents.
Pour mener à bien nos expériences, nous aurons besoin d’une version récente d’OpenSSH.

Cryptographie

À lire les documents révélés par Snowden ci-dessus, nous pouvons raisonnablement avoir le sentiment que la NSA peut 1) décrypter le chiffrement faible et 2) voler des clés. Commençons par nous concentrer sur la cryptographie. SSH supporte différents algorithmes d’échanges de clés, de chiffrement ou encore de codes d’authentification. Lors de l’établissement d’une connexion SSH, le serveur et le client indiquent à l’un et l’autre les protocoles qu’ils comprennent et en choisissent parmi ceux qu’ils comprennent tous les deux, avant de procéder à l’échange de clés. Certains des algorithmes encore utilisés à l’heure actuelle ne sont plus fiables et devraient être complètement désactivés. Parfois au détriment de l’interopérabilité, certes, mais il est important de faire évoluer les mentalités à propos de la sécurité, surtout si vous travaillez dans le domaine de l’informatique. Heureusement sur SSH les attaques de type « downgrade » ne sont pas possibles parce que les algorithmes supportés sont inclus dans la clé dérivée. Si un homme du milieu parvient à changer cette liste, le serveur et le client recalculent des clés dérivées différentes…

L’échange de clés

Dans l’ensemble il y a deux manières de s’échanger des clés : Diffie-Hellman ou Diffie-Hellman basé sur les courbes elliptiques (Elliptic curves). Les deux fournissent de la confidentialité persistante (forward secrecy), ce que la NSA déteste parce que même si elle parvient à obtenir la clé privée elle ne pourra pas déchiffrer le contenu du message. À la fin de cette étape, le client et le serveur se sont mis d’accord sur un secret (dans notre cas un nombre) sans se l’échanger directement, et donc sans qu’un tiers ne puisse le connaître. Une fois ce secret partagé chaque pair génère une clé cryptographique dérivée de ce secret en utilisant une fonction de dérivation. Dans le cas de SSH, c’est une fonction de hachage, et malheureusement il a été prouvé que les attaques par collision sur les fonctions les plus faibles peuvent permettre des attaques de type downgrade

Diffie-Hellman fonctionne avec des groupes d’entiers modulo p où p est un entier premier. Sa sûreté est basée sur la difficulté du logarithme discret. Je vous passe la description mathématique, Wikipédia le fait très bien !

Quoi qu’il en soit, OpenSSH supporte 8 protocoles d’échange de clés :

  1. curve25519-sha256: ECDH avec Curve25519 et SHA2
  2. diffie-hellman-group1-sha1: DH 1024 bits avec SHA1
  3. diffie-hellman-group14-sha1: DH 2048 bits avec SHA1
  4. diffie-hellman-group-exchange-sha1: Custom DH avec SHA1
  5. diffie-hellman-group-exchange-sha256: Custom DH avec SHA2
  6. ecdh-sha2-nistp256: ECDH avec NIST P-256 et SHA2
  7. ecdh-sha2-nistp384: ECDH avec NIST P-384 et SHA2
  8. ecdh-sha2-nistp521: ECDH avec NIST P-521 et SHA2

Nous devons veiller à trois choses ici :

  • Le bon usage de ECDH : ce qui élimine les protocoles 6 à 8 parce que le NIST est considéré comme nuisible an la matière et on ne peut s’y fier
  • La taille en bits du modulo utilisé par DH : ce qui élimine le protocole 2 car la NSA est bien connue pour avoir des supercalculateurs parmi les plus puissants du monde. 1024 bits ne sont tout simplement pas suffisants
  • La sûreté de la fonction de hachage : ce qui élimine les protocoles 2 à 4 car SHA1 est cassé. Pas la peine d’attendre le dévoilement d’une attaque de préimage qui prendrait 10 minutes sur un smartphone, autant le désactiver tout de suite

Il nous reste donc les protocoles 1 et 5. Le 1 est meilleur et l’idéal serait de ne supporter que celui-ci, mais pour des raisons de compatibilité (notamment Eclipse ou WinSCP), laissons 5.

La ligne à mettre dans /etc/ssh/sshd_config :

KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256

Et dans /etc/ssh/ssh_config :

# Github a parfois besoin de diffie-hellman-group-exchange-sha1, mais pas toujours
#Host github.com
#    KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1
 
Host *
    KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256

Si vous choisissez d’activer le 5, ouvrez /etc/ssh/moduli s’il existe et supprimez les lignes où la cinquième colonne est inférieure à 2000 :

$ awk '$5 > 2000' /etc/ssh/moduli > "${HOME}/moduli"
$ wc -l "${HOME}/moduli" # Assure-vous que le fichier généré ne soit pas vide
$ mv "${HOME}/moduli" /etc/ssh/moduli

Ou s’il n’existe pas, créez-le :

ssh-keygen -G /etc/ssh/moduli.all -b 4096
ssh-keygen -T /etc/ssh/moduli.safe -f /etc/ssh/moduli.all
mv /etc/ssh/moduli.safe /etc/ssh/moduli
rm /etc/ssh/moduli.all
Cette étape risque de prendre un peu de temps… Environ 4h sur mon petit Intel Core i3-4010U CPU @ 1.7GHz. Continuez votre lecture en attendant 🙂

L’authentification

L’échange de clés permet de s’assurer que le serveur et le client ont partagé un secret sans que personne d’autre ne le sache. Mais il nous faut aussi s’assurer qu’ils ont bien partagé ce secret entre eux et non avec un analyste de la NSA.

Authentification du serveur

Le serveur prouve son identité au client en signant la clé résultant de l’échange de clés. Il y a quatre algorithmes pour l’authentification d’une clé publique :

  1. DSA avec SHA1
  2. ECDSA avec SHA256, SHA384 ou SHA512 (selon la taille de la clé)
  3. Ed25519 avec SHA512
  4. RSA avec SHA1

Les clés DSA font 1024 bits, on désactive. Le numéro 2 implique le NIST et devrait être aussi désactivé. Autre inconvénient de DSA et ECDSA, ils utilisent l’aléatoire de la machine pour chaque signature. Si cet aléatoire n’est pas d’une grande qualité, il est possible de retrouver la clé. Heureusement, RSA avec SHA1 n’est pas un problème ici puisque la valeur à signer est déjà un hachage SHA2 (voir la section précédente). La fonction de hachage SHA1(SHA2(x)) est aussi sûre que SHA2 seule (le résultat est moins long, certes, mais il n’est pas vulnérable pour autant).

Protocol 2
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
La première fois que vous vous connectez à votre serveur après ces manipulations, il vous sera demandé d’accepter les nouvelles empreintes.

La configuration ci-dessus désactive aussi la v1 du protocole SSH, troué de partout et qui de toute manière ne devrait JAMAIS être activée. Nous pouvons aussi supprimer les clés inutilisées et générées par OpenSSH lors de son installation afin de regénérer des clés RSA et Ed25519 plus longues et plus robustes.

cd /etc/ssh
rm ssh_host_*key*
ssh-keygen -t ed25519 -f ssh_host_ed25519_key < /dev/null
ssh-keygen -t rsa -b 4096 -f ssh_host_rsa_key < /dev/null

Authentification du client

Le client aussi doit prouver son identité au serveur. Il existe différentes méthodes pour cela.

La plus simple est l’authentification par mot de passe. Celle-ci doit être désactivée immédiatement après avoir mis en place une méthode plus sûre. En effet l’authentification par mot de passe peut laisser fuiter les mots de passe en cas de compromission de serveur. Elle est aussi vulnérable aux attaques par bruteforce.

La configuration recommandée pour /etc/ssh/sshd_config :

PasswordAuthentication no
ChallengeResponseAuthentication no

La configuration recommandée pour /etc/ssh/ssh_config :

Host *
    PasswordAuthentication no
    ChallengeResponseAuthentication no

La méthode la plus sûre et la plus répandue passe par l’utilisation d’une clé publique, tout comme l’authentification du serveur évoquée précédemment.

Côté serveur (/etc/ssh/sshd_config) cela donne :

PubkeyAuthentication yes

Et côté client (/etc/ssh/ssh_config) :

Host *
    PubkeyAuthentication yes
    HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-ed25519,ssh-rsa

Les clés SSH peuvent être générées avec les commandes suivantes :

ssh-keygen -t ed25519 -o -a 100
ssh-keygen -t rsa -b 4096 -o -a 100

Et le déploiement de vos nouvelles clés publique via ssh-copy-id.

ssh-copy-id -i .ssh/id_ed25519.pub utilisateur@serveur
Il est aussi possible d’utiliser l’authentification OTP pour diminuer les conséquences d’un mot de passe perdu. Google Authenticator fourni un implémentation de TOTP, ou Timebased One Time Password. Vous pouvez aussi utiliser une liste de mots de passe uniques ou n’importe quel autre module PAM, si vous activez ChallengeResponseAuthentication

Authentification de l’utilisateur

Même avec l’authentification par clé publique, vous devriez autoriser les connections SSH uniquement depuis un nombre restreint d’utilisateurs. Ceux susceptibles d’accéder aux serveur via SSH. La directive AllowUsers dans /etc/ssh/sshd_config vous permet de spécifier quels sont les utilisateurs autorisés à se connecter via SSH. Mais cela peut s’avérer compliqué si vous avez à gérer un nombre important d’utilisateurs. D’autant plus que si vous supprimez l’un d’entre eux, celui-ci ne sera pas retiré de /etc/ssh/sshd_config, ce qui alourdit encore plus la maintenance. Une solution possible est de se tourner vers AllowGroups à la place, et d’ajouter un groupe ssh-users sur votre machine par exemple.

Ce qui donnerait dans /etc/ssh/sshd_config:

AllowGroups ssh-users

Rappels pour créer le groupe et ajouter un utilisateur dedans :

$ sudo groupadd ssh-users
$ sudo usermod -a -G ssh-users utilisateur

Chiffrement symétrique

Le chiffrement symétrique est ensuite utilisé par SSH pour chiffrer les échanges entre client et serveur une fois l’échange de clé initial et l’authentification terminés. Ici encore nous avons un certain nombre d’algorithmes à notre disposition :

  1. 3des-cbc
  2. aes128-cbc
  3. aes192-cbc
  4. aes256-cbc
  5. aes-128-ctr
  6. aes-192-ctr
  7. aes-256-ctr
  8. aes128-gcm@openssh.com
  9. aes256-gcm@openssh.com
  10. arcfour
  11. arcfour128
  12. arcfour256
  13. blowfish-cbc
  14. cast128-cbc
  15. chacha20-poly1305@openssh

Comme pour les exemples précédents, il y a quelques considérations à avoir afin de bien choisir ceux-ci :

  • Sûreté de l’algorithme : ici 1 et 10 à 12 sont éliminés. DES et RC4 sont tous les deux cassés, il faut les désactiver partout
  • Taille de clé : au moins 128 bits, plus la clé est longue mieux c’est
  • La taille de bloc : toujours au moins 128 bits. 13 et 14 sont éliminés car leur taille de bloc ne dépasse pas 64 bits
  • Le mode de chiffrement : la recommandation ici est de préférer les modes AE (Authenticated Encryption) et de n’utiliser CTR que pour des raisons de compatibilité. CTR avec Encrypt-then-MAC doit normalement être sûr (nous y reviendrons un peu plus bas).

Enfin, chacha20-poly1305@openssh doit être privilégié à AES-GCM parce que le protocole SSH ne chiffre pas la taille du message lorsqu’il est utilisé avec GCM (ou EtM). Ceci pouvant être source d’attaque, notamment via l’analyse de trafic.

On a donc pour /etc/ssh/sshd_config :

Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr

Et pour /etc/ssh/ssh_config

Host *
    Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr

Codes d’authentification de message

Le chiffrement fournit la confidentialité, un code d’authentification de message (Message authentication code, MAC) va nous fournir l’intégrité. C’est-à-dire l’assurance que le message qui a été envoyé entre deux pairs n’a pas été modifié en chemin. Et nous avons besoin des deux. Si nous avons choisi l’AE ci-dessus, inutile d’utiliser un MAC supplémentaire car l’intégrité est déjà garantie. En revanche, pour le cas de CTR, nous devons en plus choisir un algorithme pour calculer et attacher le MAC à chaque message.

Il y a plusieurs manière de procéder afin de calculer ce code. Toutes ne sont pas utiles, voici les trois principales :

  • Encrypt-then-MAC : le message est chiffré, puis le MAC est calculé à partir de celui-ci (une fois chiffré donc)
  • MAC-then-Encrypt : le MAC est calculé à partir du message en clair, puis le tout est chiffré
  • Encrypt-and-MAC : le message est chiffré, puis le MAC calculé à partir du message en clair est attaché

Seul Encrypt-then-MAC doit être utilisé, point. L’utilisation de MAC-then-Encrypt a conduit à suffisamment d’attaques sur TLS alors que Encrypt-then-MAC n’en a pas présenté autant sur SSH. La raison à cela est que si jamais vous recevez le message d’un attaquant, plus vous allez le manipuler et plus vous aller lui laisser de chances d’obtenir des informations. Dans le cas de Encrypt-then-MAC, le MAC est vérifé et s’il est incorrect, rejeté. Bim. Une étape, aucun moyen d’obtenir des informations. Alors que dans le cas de MAC-then-Encrypt, comme le MAC est calculé à partir du message en clair il va falloir déchiffrer le message afin de vérifier le MAC. Un échec de déchiffrement (dû à un mauvais padding CBC par exemple) pourrait prendre moins de temps qu’il n’en faut pour la génération de l’échec de vérification du MAC, et donner du temps à l’attaquant pour accéder à des informations. Le problème est le même avec Encrypt-and-MAC.

Voici les choix possibles ici :

  1. hmac-md5
  2. hmac-md5-96
  3. hmac-ripemd160
  4. hmac-sha1
  5. hmac-sha1-96
  6. hmac-sha2-256
  7. hmac-sha2-512
  8. umac-64
  9. umac-128
  10. hmac-md5-etm@openssh.com
  11. hmac-md5-96-etm@openssh.com
  12. hmac-ripemd160-etm@openssh.com
  13. hmac-sha1-etm@openssh.com
  14. hmac-sha1-96-etm@openssh.com
  15. hmac-sha2-256-etm@openssh.com
  16. hmac-sha2-512-etm@openssh.com
  17. umac-64-etm@openssh.com
  18. umac-128-etm@openssh.com

Comment faire le tri là-dedans ?

  • Sûreté et solidité de l’algorithme : pas de MD5 ni de SHA1
  • Encrypt-then-MAC
  • La taille du tag : au moins 128 bits, ce qui élimine umac-64-etm
  • La taille de clé : au moins 128 bits, ce qui n’élimine personne \o/

L’extrait pour /etc/ssh/sshd_config :

MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com

Et pour /etc/ssh/ssh_config :

Host *
    MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com

Prévenir le vol de clé

Même si la confidentialité persistante doit en partie nous protéger de cela, il est important de garder nos clés à l’abri des regards indiscrets. La NSA a une énorme base de données de clés volées et vous ne souhaitez pas que la vôtre y figure.

Durcir son système

OpenSSH dispose de fonctionnalités non-documentées et rarement utilisées. UseRoaming en fait partie et une vulnérabilité la concernant a été récemment découverte. Autant la désactiver tout de suite.

/etc/ssh/ssh_config :

Host *
   UseRoaming no

Le reste n’est autre que bon sens et bonnes pratiques. Cet article n’a pas pour but d’être un guide complet sur la sécurité de votre machine, néanmoins il est toujours bon de rappeler :

  • N’installez pas ce dont vous n’avez pas besoin. Chaque ligne de code ou chaque programme sont autant de chance de trouver un bug ou une faille de sécurité. Moins de lignes, moins de programmes = surface d’attaque réduite
  • Utilisez du logiciel libre. Le logiciel libre contient du code qui a été relu ou que vous-même pouvez relire. Il n’y a aucun moyen de faire ça sur du code propriétaire
  • Maintenez vos logiciels à jour, les nouvelles versions corrigent très souvent des bugs ou des trous de sécurité en plus d’apporter de nouvelles fonctionnalités

Stockage de votre clé

Vous devriez utiliser un mot de passe fort pour la clé privée de votre client. Vous pouvez en plus utiliser ssh-keygen -o -a pour ralentir les tentatives de cassage en itérant la fonction de hash plusieurs fois.

Malheureusement côté serveur impossible de chiffrer la clé utilisée sinon OpenSSH ne pourrait pas l’utiliser… La première protection que vous avez à ce niveau ce sont les droits d’accès à appliquer sur le fichier contenant la clé.

Conclusion

C’est certainement une bonne idée de tester tous les changements apportés. ssh -v apporte un certain nombre de détails, notamment les algorithmes utilisés, pratique pour déboguer rapidement. Soyez très prudent lorsque vous changez la configuration SSH d’une machine distante. Faites en sorte de toujours garder une session active, sans jamais redémarrer sshd avant d’être sûr de soit. Vous pouvez par ailleurs demander à OpenSSH de recharger la configuration sans redémarrer en utilisant un SIGHUP. Pour être à l’abri de tout risque, vous pouvez aussi démarrer temporairement un serveur SSH sur un nouveau port le temps de faire vos tests 🙂

Et si tout est bon, alors…

Bonhomme qui danse

Sinon, c’est peut-être à cause d’un problème de compatibilité ? Essayez de convaincre les personnes qui vous bloquent en insistant sur le fait que leurs outils de sécurité ne sont pas à jour 🙂 L’auteur original de l’article a créé une page de wiki sur GitHub que tout le monde peut enrichir en proposant des configurations SSH sûres et compatibles avec le plus de services possible.

Bonus

Aeris nous propose un ensemble d’outils très pratiques pour tester la solidité du chiffrement sur HTTPS, XMPP et… SSH ! Une bonne occasion de tester votre configuration et de faire chauffer son serveur. Ça se passe par ici : https://tls.imirhil.fr/ssh/. Un grand merci à lui pour son travail.

Le résultat doit être parsemé de vert, de gris et d’un jaune.

Sources :
Cet article est une traduction libre de Secure Secure Shell, que l’auteur, stribika, m’a gentiment encouragé à réaliser. Tout le travail de recherche lui revient donc, et j’en profite pour le remercier.

Cet article vous a plu ? Partagez-le sur les réseaux sociaux !

Twitter Facebook Google Plus email