Arrêtez le TOFU, et utilisez des certificats d'hôtes

04-11-2022

L’une des règles les plus importantes en sécurité, c’est de ne pas ignorer les alertes. Prenons un exemple de la vie de tous les jours : imaginons que votre activité se porte bien et que votre administrateur système ajoute un serveur à l’infrastructure. Un jour, vous tentez de vous y connecter et vous tombez sur le message suivant :

> ssh ca.redwatch.io

The authenticity of host 'ca.redwatch.io (172.18.0.3)' can't be established.
RSA key fingerprint is SHA256:JlEdkzIPBxqBZ95UZ/fBAwtWhJlj8NQtXseDRd+5V+o.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])?

La plupart d’entre nous a appris à ignorer cette alerte et à valider, un peu comme des CGUs barbantes à l’inscription d’un service. Cette validation sans plus de précaution a un nom, elle s’appelle le TOFU (ou Trust On First Use). Et si c’était grave ? Et si, en réalité, nous faisions confiance à la mauvaise personne ?

Improbable ? Malheureusement, ce critère n’est pas une bonne évaluation de la sécurité d’un système.

Pour comprendre comment c’est possible, détaillons comment une communication SSH se déroule. Pour se connecter, SSH exécute une sous-opération ssh-keyscan [host] pour récupérer la clé publique du serveur et la compare à une éventuelle ligne dans known_hosts. C’est là que ça coince : SSH s’appuie sur le routage habituel d’Internet, il est donc possible avec un peu de technique de prétendre être [host]. Tout ce qu’il faut à l’attaquant, c’est être dans un sous-réseau plus près du client que le serveur légitime ; c’est le fameux Man-In-The-Middle.

Comment légitimer un serveur ?

Donc, puisque nous ne connaissons pas encore le serveur et qu’on ne peut pas faire confiance au réseau, comment on fait pour ne pas ignorer cette alerte ?

La méthode la plus immédiate est manuelle, il s’agit de contacter votre admin sys pour comparer les empreintes. Rien de plus simple :

> ssh-keygen -lf /etc/ssh/ssh_host_rsa_key.pub
3072 SHA256:JlEdkzIPBxqBZ95UZ/fBAwtWhJlj8NQtXseDRd+5V+o root@ca.redwatch.io (RSA)

Comme on le constate ici, les empreintes sont identiques et le serveur est bien celui qu’il prétend. Le problème, c’est que ça ne passe pas à l’échelle ; tout changement dans l’infrastructure ou tout nouvel arrivant dans l’équipe implique de relancer le processus de validation.

Pour conserver une sécurité maximale sur l’architecture sans avoir une charge de travail linéaire au changement, il faut de l’automatisation : les certificats SSH. Un certificat SSH fonctionne de la façon suivante :

  1. le client contacte le serveur,
  2. le serveur présente son certificat d’identité signé,
  3. le client reconnaît l’autorité de signature et accepte le serveur.

Grâce à l’autorité de signature, vous pouvez vous connecter à 1, 2, 1000 serveurs si vous le souhaitez, vous n’aurez plus de TOFU. Convaincu ? Alors on met les mains dans le cambouis !

Mettre en place un certificat SSH

L’autorité

Ce nouveau fonctionnement faisant apparaître un nouveau participant, configurons-le en premier. La première étape ne devrait pas vous choquer, il s’agit de créer une bi-clé SSH :

> mkdir /root/.ssh/authority && cd /root/.ssh/authority
> ssh-keygen -f server_ca
> cat server_ca.pub
ssh-rsa AAAAB3Nza[...]VfrR+S6uh+LP8= root@ca.redwatch.io

/!\ cette bi-clé ne sert pas à authentifier le serveur mais à signer toutes les autres clés. Il est donc vital que le serveur d’autorité ainsi que sa bi-clé soient l’objet d’une sécurité maximale.

Notre autorité étant lui-même un serveur, on va signer sa clé d’accès native et en faire un certificat :

> ssh-keygen -s server_ca -I CA -h -n ca.redwatch.io -V +12w /etc/ssh/ssh_host_rsa_key.pub
Signed host key /etc/ssh/ssh_host_rsa_key-cert.pub: id "CA" serial 0 for ca.redwatch.io valid from 2022-11-02T15:19:00 to 2023-01-25T15:20:18

Le certificat étant créé, il faut dire au serveur SSH de s’appuyer dessus :

> echo "HostCertificate /etc/ssh_host_rsa_key-cert.pub" >> /etc/ssh/sshd_config
> systemctl restart sshd

Le client

Côté client, faisons (re)connaître l’autorité par l’entremise de sa clé publique :

# cat /etc/ssh/ssh_known_hosts
@cert-authority *.redwatch.io ssh-rsa AAAAB3Nza[...]VfrR+S6uh+LP8= root@ca.redwatch.io

Il ne nous reste plus qu’à tenter de nous connecter à notre serveur :

> ssh ca.redwatch.io
root@ca.redwatch.io's password:

Succès, pas de TOFU ! Chose notable, aucun known_hosts n’a été mis à jour avec l’identité du serveur atteint.

Bonus : le cycle de vie complet

Une fois l’autorité créée, la certification d’un serveur « Bob » se déroule de la façon suivante :

séquence certificat ssh

Comme vous le voyez, la certification SSH possède de grands avantages pour un coût faible, et fonctionne de façon similaire à la certification HTTPS. Nous n’avons ici parlé que de la certification d’hôtes ; un prochain article suivra pour vous montrer comment certifier des utilisateurs.

Comme d’habitude, vous pouvez retrouver le code pour essayer par vous-même sur le dépôt d’exemple.


Sources:


    Ce billet vous a plu ? Inscrivez-vous à notre newsletter pour ne manquer aucun article (Si vous ne voyez pas le formulaire, désactivez temporairement uBlock).