Comment fonctionne SSH

SSH est l’acronyme des mots Secure Shell et c’est en fait à la fois un programme et un protocole de communication.

SSH a été crée par le finlandais Tatu Ylönen en 1995. Cet outil répondait à une problématique simple : comment se connecter à un ordinateur/serveur/matériel distant de façon sécurisée. A l’époque (et c’est toujours d’actualité), nous avions le protocole telnet (terminal network) qui permettait d’administrer à distance une machine via un terminal. Cependant il y avait un gros problème lié à ce protocole : les communications étaient envoyées en clair sur le réseau.

Du coup si un pirate se pointe sur le réseau et sniffe la session d’authentification eh bien il a accès au matériel ou à la machine cible. Avec SSH, ce n’est plus possible puisque les communications sont chiffrées ! Le but de cet article sera de montrer justement comment les communications sont chiffrées. Ensuite on verra quels sont les différents moyens d’authentification. Mais avant tout il faut installer un serveur SSH…

I/ Installer SSH

La référence SSH c’est OpenSSH, pour l’installer rien de plus simple :

sudo apt install openssh-server

Pour vous connectez en SSH il vous suffira d’entrer cette commande :

ssh <compte_utilisateur>@<serveur_cible>

Voilà, on va pouvoir passer aux choses sérieuses  !

II/Initialisation d’une connexion chiffrée

Pour les besoins de l’article j’ai lancé Wireshark afin d’avoir un dump des trames envoyées entre le client et le serveur lors de l’initialisation de la connexion et voici ce que j’ai récupéré :

ssh1.png

Notez que je ne me suis pas encore authentifié à ce moment là. Et pourtant j’ai déjà des trames en claires et des trames chiffrées qui sont envoyées. Voyons en détails ce qu’il s’est passé :

ssh2.png

Les deux première trames contiennent le header de l’application SSH. Lorsque vous initiez une connexion SSH, la première chose que font le serveur et le client c’est de s’envoyer leurs headers SSH afin de voir quelles versions de SSH sont utilisées et du coup se synchroniser (un serveur qui utilise SSHv1 ne pourra pas forcément communiquer avec un hôte qui utilise sshv2 et vis vers ça).

Voici ce que l’on obtient si on initialise une connexion via netcat :

ss3.png

Les deux trames suivantes :

ssh4.png

Contiennent les différents protocoles de chiffrement que peuvent utiliser le client le serveur. Si on s’aventure dans la trame et qu’on se rend dans la couche application on trouvera ceci :

ssh5.png

Si on regarde attentivement on retrouve l’algorithme Diffie-Hellman dont j’ai déjà détaillé le fonctionnement ici.

Le comportement par défaut du serveur et du client est d’utiliser le protocole le plus sécurisé possible. D’ailleurs un vecteur d’attaque contre le SSH est justement de s’interposer entre le client et le serveur est de proposer à l’un comme à l’autre un protocole de chiffrement volontairement faible afin de pouvoir par la suite le casser et déchiffre les requêtes à la volé ! Mais ce n’est pas le sujet de cet article  !

Comme vous pouvez le voir dans le trames suivantes, le protocole de création de clés utilisé par le serveur et le client est Diffie-Hellman :

ssh6.png

Cet algorithme va permettre au client et au serveur de créer un secret commun qui sera utilisé afin de chiffrer les données futures. Encore une fois je vous invite à lire l’article sur Diffie-Hellman, le principe mathématique est extrêmement simple à comprendre et pourtant ça suffit pour empêcher toute attaque sur le chiffrement  ! Dans ces deux trames on va trouver les paramètres nécessaires à la création du secret commun entre le client et le serveur (des valeurs numériques très grandes).

Dernière trame :

ssh7.png

Ce paquet ne contient pas grand chose, juste un message « New Keys » qu’on peut considérer comme étant un packet ACK (acknowledgement).

Voilà ! Les deux communicant disposent tous les deux d’une même clé permettant de chiffrer et déchiffrer le contenu de leurs futures communications. A partir de maintenant ils sont capables d’envoyer des message chiffrés :

ssh8.png

Passons à la partie authentification.

III/ Authentification SSH

Nous disposons de plusieurs manières de nous authentifier via SSH :
-Via un nom d’utilisateur / mot de passe
-Via un couple de clés privées/publiques

Voyons voir comment ces deux méthodes fonctionnent.

  • Via nom d’utilisateur / mot de passe :

Le protocole SSH utilise l’authentification locale. C’est à dire qu’il se sert des fichiers /etc/passwd et /etc/shadow afin d’authentifier les utilisateurs. Du coup, pour pouvoir vous authentifier via SSH il suffit de créer un utilisateur sur votre machine local et d’utiliser ses identifiants.

Par exemple si je veux me connecter à ma machine je vais devoir spécifier que je me connecte en ssh avec mon compte utilisateur soit defte :

ssh9.png

Il ne me reste plus qu’à entrer mon mot de passe pour être connecté sur ma machine :

ssj10.png

Stoooooooooooooooop ! Je vous vois venir les petits malins ahah ! Non vous ne pourrez pas vous connecter au compte root via SSH. Enfin… Si mais il faudra modifier le fichier de configuration de votre serveur SSH :

Pour cela il faudra éditer le fichier /etc/sshd et modifier la ligne :

#PermitRootLogin prohibit-password

en

PermitRootLogin yes

Cependant gardez bien en tête que si l’option est désactivée par défaut c’est parce qu’il est dangereux de l’activer ! Si un pirate casse votre mot de passe root eh bien il aura accès à votre machine à distance -> Not cool  !

  • Authentification via clé :

L’authentification par clé rend plus simple la gestion des mots de passe SSH. En effet si vous avez 20 serveurs et que pour chaque serveur vous avez un compte avec un mot de passe différent…. Ben ça va être bien compliqué à gérer.

Par contre si je vous dis qu’avec deux fichiers et un mot de passe on peut s’authentifier sur toutes nos machines, là ça devient intéressant !

Le principe est simple, on va générer deux clés :
-Une clé privée qui sera stockée sur la machine du client et qu’il ne faut surtout pas dévoiler
-Une clé publique qui sera stockée sur la machine serveur

Pour générer ces clés on utilisera l’outil de génération d’OpenSSH via la commande suivante :

ssh-keygen -t rsa

ssh11.png

L’outil va vous demander ou vous voulez stocker les clés (par défaut dans le répertoire /home/{votre répertoire personnelle}/.sshd/). Ensuite il va vous demander un mot de passe. Ce mot de passe servira à protéger votre clé privée d’éventuels intrus.

Du coup si on regarde le contenu du répertoire /id_rsa, on trouvera ceci :

ssh12.png

Nous avons nos deux clés, id_rsa est notre clé privée tandis que id_rsa.pub est notre clé publique. Nous avons aussi un fichier « known_hosts » dans lequel on trouve la liste des hash des clés publiques des serveurs que l’on a déjà visité.

Souvenez vous, lors de la création des clés publiques/privées, un hash a été calculé :

ssh13.png

A chaque fois que vous allez vous connecter (coté client) à un nouveau serveur SSH, une banderole va s’afficher en disant qu’il (le client) ne connaît pas ce hash de clé (et donc que c’est la première fois que vous vous connectez à ce serveur). Acceptez de vous y connectez, et le hash de la clé sera stocké dans le fichier known_hosts.

Dernière étape, il va falloir déposer notre clé publique dans le fichier/.ssh/authorized_keys sur le serveur. Pour cela on peut utiliser cette commande :

ssh-copy-id defte@localhost

ssh14.png

Entrez le mot de passe de votre clé privée quand on vous le demande et votre clé sera ajoutée. Maintenant connectez vous via SSH à l’aide de votre clé privée (option -i) :

ssh -i <votre_clé_privée> <compte_user>@<cible>

ssh15.png

Vous aurez seulement besoin d’entrer le mot de passe de votre clé privée (celui que l’on a renseigné lors de la création des clés) et vous serez connectés ! Du coup au lieu d’avoir un identifiant et un mot de passe pour chaque serveur on aura deux fichiers (clé privée et clé publique) ainsi que le mot de passe de la clé privée et… C’est tout  !

Mais du coup comment ça se passe l’authentification par clé privée/publique ? Après tout n’importe qui est en mesure de dire qu’il a clé privée. Donc il faut à un moment vérifier que la clé privée qui est envoyée correspond bien à la clé publique stockée sur le serveur.

Pour cela le serveur va envoyer un challenge (une suite de caractères, un calcul mathématique etc…) chiffré à l’aide de la clé publique de l’utilisateur et demander au client de lui renvoyer la réponse de ce challenge. Cela implique bien évidemment que le client puisse déchiffrer le challenge (et donc qu’il possède la bonne clé privée). Schématiquement ça donne ça :

ssh16.png

Voilà vous êtes connectés !

IV/ Utiliser SFTP

SFTP (à ne pas confondre avec FTP over SSL) est un outil qui va nous permettre de manipuler des fichiers sur un serveur à distance (le tout de manière sécurisée). Pour vous connectez à votre serveur vous pouvez utiliser cette commande :

sftp {nom_d'utilisateur}@{serveur_cible}

Pour ma part je ne vais pas me connecter via mon nom d’utilisateur / mot de passe mais via ma clé privée (voir cet article pour plus d’informations) :

ssh17.png

Nous sommes connectés. Pour avoir un aperçu des commandes disponibles nous pouvons utiliser la commande help :

ssh18.png

Pas mal de choses sont possibles avec SFTP. On peut se balader dans les répertoires, en créer, en supprimer mais surtout on peut transférer des fichiers depuis notre machine locale jusqu’à la machine distante et vis vers ça.

Pour cela on utilise deux commandes : put et get dont voici les syntaxes :

put "chemin_local" "chemin_distant"

et

get "chemin_distant "chemin_local"

Je ne vais pas m’attarder plus longtemps sur SFTP, vous trouverez tout ce dont vous avez besoin dans la documentation en tapant la commande help  ! Pour quitter SFTP il vous suffira d’entrer la commande suivante :

bye

C’est tout pour le SSH. Plutôt cool non ?! Bon bah du coup vous pouvez désactiver le service Telnet hein ! Ça sera plus safe pour tout le monde  !