Authentification double facteur TOTP pour serveur ssh

Pour accéder à des ressources numériques il est nécessaire de s’authentifier. C’est la procédure qui permet de vérifier l’identité de la personne qui accède à la ressource. Jusqu’à nos jours, on utilise couramment un identifiant (ou login) associé à un mot de passe connu uniquement par la personne qui a accès à la ressource. On sait également que cette méthode n’est pas très sûre. Un mot de passe trop simple peut facilement être deviné. C’est pour cela qu’il est recommandé d’utiliser des mots de passe complexes et des mots de passes différents pour chaque ressource. Plus grave : on ne peut pas savoir si un mot de passe est copié. Pour se protéger du vol de mot de passe, la solution est d’ajouter à «ce que l’on sait» (le mot de passe) un deuxième facteur : «ce que l’on a»1.

Une première idée est d’utiliser des paramètres biologiques comme les empreintes digitales ou l’iris. Mais les empreintes digitales sont faciles à copier et même à reproduire. Naturellement il ne sera pas possible de changer ses empreintes digitales lorsque le vol sera constaté. La «biométrie» est par conséquence une très mauvaise idée.

Une seconde solution est d’utiliser un carte à puce. Malheureusement il n’existe pas de façon standard de lire une carte à puce et la perte de l’objet va provoquer des frais importants.2

La solution la plus pratique est alors d’utiliser un code à usage unique: un «One Time Password». Un code doit être ajouté après l’identifiant et mot de passe. S’il est enregistré, vu, copié, il ne pourra de toute façon plus jamais être utilisé. En cas de perte, il suffit de révoquer l’ensemble des codes prévus : inutile de couper des mains ou crever des yeux.
Plusieurs solutions existent pour avoir accès à un code à usage unique. Il existe par exemple des équipements électroniques dédiés : des «token». Cependant ils peuvent être égarés et leur remplacement entrainera des frais. Une solution simple est la grille imprimée sur papier. Celle-ci peut également être égarée ou pire photocopiée.
La meilleur solution est alors l’usage d’un smartphone. Cela permet en plus de générer un code utilisable pendant 30 secondes : un «Time OTP». Il suffit que le smartphone et le serveur soient synchronisés à quelques secondes près. Ceci est devenu un standard pour les équipements connectés sur Internet.

Ce premier billet sur le sujet va nous permettre d’installer une authentification TOTP sur un serveur openssh.

Génération des codes

Nous allons commencer par utiliser l’utilitaire oathtool. On l’installe comme d’habitude avec apt-get install oathtool.

On génère ensuite 30 caractères hexadécimaux aléatoires.

$ head -10 /dev/urandom | md5sum | cut -b 1-30
e3e3c1482b1b46b63d359f5c3848d0

Ces 30 caractères sont la clé secrète qui sera partagée entre le serveur et le smartphone.

oathtool nous permet de générer un code valide en fonction de cette clé.

$ oathtool -v --totp e3e3c1482b1b46b63d359f5c3848d0
Hex secret: e3e3c1482b1b46b63d359f5c3848d0
Base32 secret: 4PR4CSBLDNDLMPJVT5ODQSGQ
Digits: 6
Window size: 0
Step size (seconds): 30
Start time: 1970-01-01 00:00:00 UTC (0)
Current time: 2015-09-23 12:29:20 UTC (1443011360)

$ oathtool --totp e3e3c1482b1b46b63d359f5c3848d0
745909

$ oathtool --totp --base32 4PR4CSBLDNDLMPJVT5ODQSGQ
745909

Vous remarquez ci-dessus que pour faciliter la lecture et la copie des 30 caractères hexadécimaux on peut utiliser une conversion en base 32. On obtient 24 caractères ASCII.
Ces 24 caractères peuvent être représentés sous la forme de 8 blocs de 4 caractères ou facilement convertis en QR Code :

$ qrencode otpauth://totp/MyOtp@me?secret=4PR4CSBLDNDLMPJVT5ODQSGQ -l H -o qrcode-fake.png

otpauth://totp/MyOtp@me?secret=4...

Double facteur pour openssh

Nous allons utiliser pam pour activer l’authentification double facteur avec le module libpam-oath (comme d’habitude : apt-get install libpam-oath).

On remplace alors le module common-auth par le module requis pam_unix, suivi du module pam_oath et naturellement pam_deny s’il y a échec des authentifications.

$ sudo vi /etc/pam.d/sshd 
...
#@include common-auth
auth    requisite      pam_unix.so
auth    sufficient pam_oath.so usersfile=/etc/users.oath window=10 digits=6
auth    required        pam_deny.so

...

pam_oath lit le fichier des utilisateurs /etc/users.oath qui doit absolument être protégé et donc ne doit être accessible que à root

$ sudo vi /etc/users.oath
HOTP/T30/6  root    -   xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
HOTP/T30/6  me    -   e3e3c1482b1b46b63d359f5c3848d0

$ sudo chmod 600 /etc/users.oath

me est le login utilisateur définit dans /etc/passwd3.

Pour terminer, la configuration du serveur openssh doit être modifiée pour permettre de saisir le deuxième facteur. Il suffit de positionner la clé ChallengeResponseAuthentication à yes

$ sudo vi /etc/ssh/sshd_config
...
#ChallengeResponseAuthentication no
ChallengeResponseAuthentication yes
...

$ sudo /etc/init.d/openssh reload

Il n’y a plus qu’à l’utiliser depuis une machine distante:

$ ssh me@myserver.org
Password: 
One-time password (OATH) for `me':

Il ne faut pas oublier qu’il s’agit ici d’une protection supplémentaire sur les connexions ssh contre le vol de mot de passe. Si vous laisser un accès publique à votre serveur ssh, une protection spécifique contre les attaques en force brute est depuis longtemps indispensable.

Clients TOTP pour smartphone

Comme TOTP est défini par la RFC6238, il existe de multiple clients. Cependant il est impératif de protéger la clé sur le smartphone, il faut alors privilégier une solution Open Source où le code a été vérifié.

Voici trois clients qui permettent simplement de scanner un QR Code pour ajouter la clé secrète.

Pour Android, le gestionnaire de paquets libres F-Droid propose Android Token ou une version expurgée de Google Authenticator. FreeOTP est développé par RedHat et est disponible sur GooglePlay pour Android et l’AppleStore de Iphone.

Android Token Google Authenticator FreeOTP

Vous pouvez noter la représentation graphique des 30 secondes de validité mais également l’usage de la même application pour se connecter à Facebook ou Google4. J’en parlerai certainement dans un futur billet.

Anticiper les problèmes

Perte de la clé

Il est impératif de protéger la clé qui se situe sur le serveur dans /etc/users.oath mais également sur le smartphone. On peut envisager de garder une copie de secours en imprimant le QR Code ou sous forme ASCII dans un container chiffré. Toute autre copie devient potentiellement dangereuse puisqu’il peut y avoir copie de cette clé. Si le smartphone est perdu ou détruit il sera nécessaire de la changer.

Synchronisation

L’horloge du serveur peut dériver au cours du temps. J’ai déjà observé des dérives de 2 minutes par an.

Cela ne pose pas vraiment de problème parce que le paramètre window=10 permet de générer 10 codes valides. Cela représente une fenêtre valide maximale de 3 minutes 30.

Néanmoins il est préférable de s’assurer de la synchronisation du serveur par exemple avec le fichier /etc/cron.weekly/ntpdate ci dessous :

#!/bin/sh
/usr/sbin/ntpdate pool.ntp.org 1> /dev/null 2>&1

Il doit être exécutable $ chmod +x /etc/cron.weekly/ntpdate.
Le smartphone se synchronise sur le réseau téléphonique.

Au pire, si on dispose d’un accès physique au serveur, on synchronise manuellement : pam-oath ne s’applique ici que à sshd et non aux consoles physiques.

Pour un serveur hébergé dans un datacenter où l’accès peut être compliqué, il faut envisager un accès avec un compte limité qui permet de vérifier l’heure du serveur et ne protéger que l’accès à sudo

#%PAM-1.0

# OATH 2 factor for su
auth requisite pam_oath.so usersfile=/etc/users.oath window=20 digits=6

@include common-auth                                                                                                                    
@include common-account                                                                                                                 
@include common-session-noninteractive

On peut également imaginer un webservice qui n’affiche que l’heure du serveur.

oathtool permet ensuite de générer un code pour l’heure erronée :

$ oathtool --totp --now "2008-04-23 17:42:17 UTC" --base32 4PR4CSBLDNDLMPJVT5ODQSGQ
048548

Notes

  1. Pour retirer de l’argent avec une carte bleu, il faut «posséder» la carte et «connaitre» le code de cette carte.
  2. Encore un «succès» d’une technologie française ?
  3. Pour un grand nombre d’utilisateurs il faudra envisager de déléguer la gestion à un serveur radius
  4. TOTP est également utilisable avec GitHub, Amazon, Hootsuite, … La liste est longue. Seul Twitter utilise une version spécifique utilisable seulement depuis son application mobile.