ToutSurTout.biz
Using YubiKey Neo as Gpg Smartcard for SSH Authentication


https://stafwag.github.io/blog/blog/201 … ntication/

Petit défi utile que je me suis lancé : en cas d'urgence, comment me connecter, via SSH, à mes serveurs persos et à ceux d'ARN depuis le taff ?

Sachant que :
   * J'amène rarement mon ordi portable perso au taff car c'est pas commode dans les transports ;

   * Je ne suis pas root sur mon desk@taff (j'ai un wrapper python setuid root pour install/remove des softs et start/stop des services, rien de plus, même la modification de fichiers de conf dans /etc m'est interdite). En revanche, une team entière est root sur mon desk ;

   * Hors de question d'amener ma clé privée SSH au taff, même sur une clé USB : root pourrait me la voler. Conceptuellement, c'est une connerie : la clé privée ne transite pas sur un ordi sur lequel vous n'êtes pas le seul root, que ça soit un ordiphone perso ou un desk@taff ;

   * Pas d'authentification par mot de passe sur mes serveurs, je n'ai pas envie de lutter contre l'océan nommé bruteforce à coup de fail2ban & co.


Idée : utiliser la fonctionnalité smartcard GPG de ma Yubikey Neo (https://www.yubico.com/products/yubikey … bikey-neo/) + gpg-agent qui simule aussi le ssh-agent. Auth par clé tout à fait standard, simplement la clé privée est stockée sur la Yubikey et ne peut en être extraite (les spécs ne prévoient pas cette opération, une attaque physique reste sûrement possible mais demande temps et compétences, ça exclu donc 99,9% des attaquants potentiels). En cas de perte/vol de la clé, il y a un PIN avec 3 essais possibles (l'admin PIN peut reset l'user PIN, 3 essais là aussi) + je vire la partie publique des authorized_keys de mes serveurs à coup d'Ansible dès que je constate la disparition (même temporaire) de ma Yubikey. Oui, root@taff peut encore capturer mon PIN avec un keylogger... C'est hors scope : s'il y a un keylogger sur mon desk@taff, j'aurai d'autres problématiques dans le sens où root aura capturé beaucoup d'autres choses...

La Yubikey ne permet pas d'utiliser des clés RSA plus longues que 2048 bits, ce qui est un peu juste de nos jours (le Référentiel Général de Sécurité de l'ANSSI admet 2048 comme taille minimale, 3072 comme taille recommandée, voir http://www.ssi.gouv.fr/entreprise/regle … gs-v-2-0/, document B1). Conséquence : ce n'est pas ma "vraie" clé GPG que je stockerai sur ma Yubikey, ma Yubikey me servira uniquement pour de l'auth SSH sur mes serveurs et ceux d'ARN, elle ne sera donc pas publiées sur les serveurs de clés pour ne pas embrouiller les personnes qui voudraient m'envoyer des mails chiffrés.

Il est également possible de générer une clé primaire et des sous-clés (pour un rappel sur le principe de fonctionnement des sous-clés, voir https://wiki.debian.org/fr/Subkeys) et de stocker les sous-clés sur la Yubikey en gardant la clé primaire à la maison. Je n'ai pas besoin de cette complexité dans mon cas d'utilisation. Si vous pensez en avoir besoin, d'autres tutos sont plus adaptés.


Pour la mise en pratique, on suit et on adapte pour Debian GNU/Linux Jessie le tutoriel.

1) sudo apt-get install yubikey-personalization

2) La première fois, ykinfo -v retournera « USB error: Access denied (insufficient permissions) » et il faudra ajouter une règle udev pour autoriser votre user en lecture+écriture dans /etc/udev/rules.d/99-yubikeys.rules : « ACTION=="add|change", ATTR{idVendor}=="1050", OWNER="guigui", MODE="0600" » (remplacez « OWNER="guigui" » par votre username. À la prochaine insertion de la yubikey, les permissions seront OK.

3) ykinfo -v
version: 3.3.0

4) On active l'interface smartcard en plus de la fonctionnalité OTP (le man de ykpersonalize explique les différentes configs possibles) :  ykpersonalize -m82 . L'interface smartcard sera activée à la prochaine insertion de la Yubikey et elle apparaîtra avec un gpg --card-status.

5) Changer l'user PIN et l'admin PIN : gpg --change-pin .

6) On génère les paires de clés directement sur la carte : gpg --edit-card puis « admin » dans le prompt GPG puis « generate ». Je n'ai pas gardé une copie des clés sur ma machine. J'ai mis une période avant expiration d'un an. Attention : cela veut dire que le seul exemplaire existant de la clé privée se trouve sur la yubikey et n'est pas extractible et les clés publiques se trouvent uniquement sur la machine utilisée !

7) Récupérer le fingerprint de la clé d'authentification : gpg --card-status | grep "Auth". À partir de là, il faut récupérer l'ID long (64 bits) de cette clé : il s'agit des 16 derniers chiffres (en hexa A-F sont des chiffres wink ). Il faut virer les espaces.

8) gpgkey2ssh <ID_long_de_l'étape_précédente>. On récupère donc ce qu'il faut mettre dans l'authorized_keys de nos serveurs. smile

9) Si ce n'est pas encore fait, il faut virer le fake agent-gpg de GNOME/MATE

10) On active le support SSH de l'agent-gpg : echo "enable-ssh-support" >> ~/.gnupg/gpg-agent.conf

11) On installe le support des smartcard pour GPG : apt-get install scdaemon

12) Fermer la session et revenir. Le bon agent GPG sera lancé, avec le support SSH. ssh-add -l doit montrer la clé présente sur la yubikey.

13) J'ai remarqué que la règle udev n'est plus nécessaire (probablement depuis l'étape 4 mais sans certitude) : la clé fonctionne directement sur n'importe quelle machine GNU/Linux. Tout est donc dans $HOME et le seul droit dont nous avons besoin est installation de logiciels. Achievement unlocked ! \o/


À partir d'ici, mes serveurs peuvent m'authentifier à partir de ma yubikey... mais comment puis-je être sûr de l'identité du serveur en face (DNS menteur, hijack routing...) ? Il faut vérifier la fingerprint de la clé publique du serveur la première fois puis c'est stocké dans known_hosts... Sauf que là, je ne suis pas le seul root... Le fichier known_hosts n'est donc pas fiable. Comment faire ?
   * Soit amener la fingerprint de chacun de mes serveurs persos/assos sur un morceau de papier. Ça se loge dans mon porte-feuilles donc c'est OK pour moi. Avant chaque connexion, il faudra supprimer le fichier know_hosts existants (il a pu être altéré entre deux connexions à mes serveurs).

   * Soit DNSSEC + SSHFP + un récursif cache local à la machine validant. Achievement unlocked ! \o/

Toutes les autres idées que j'ai eu foirent :
   * Signer un known_hosts valide chez moi avec la yubikey. Pour valider la signature, il faut la clé publique. Comment on la récupère de manière sûre ?
       * On ne peut pas récupérer la clé publique depuis la smartcard ni la dériver de la clé privée car ça nécessite de gpg --import la clé privée (puis de gpg --export)... Ce qui n'est pas possible avec une smartcard. Voir : https://lists.gnupg.org/pipermail/gnupg … 28281.html .

       * On a dit qu'on ne mettait pas notre clé sur les serveurs de clés vu sa faiblesse et la possibilité de confusions.

       * Sur une smartcard (et donc une yubikey), il est possible de stocker une URL où récupérer la clé (gpg --card-edit + « admin » + « url » pour définir, gpg --card-edit + « fetch » pour récupérer la clé) mais alors il faut vérifier la clé (root a pu MITM, même avec TLS puisqu'il contrôle la liste des AC x509 reconnues sur le desk@taff)... Retour au problème initial.

       * Clé USB ? Il faut avoir une clé de plus dans sa poche. Si on stocke la clé sur le desk@taff, root peut la remplacer (ainsi que le known_hosts) par une paire qu'il a généré lui-même avec une identité avec mon nom/prénom. C'est donc la fingerprint qu'il faut vérifier.

   * On pourrait chiffrer un known_hosts valide et l'amener au taff et même le stocker au taff : il faudrait forcément la yubikey pour le déchiffrer. Si GPG accepte de déchiffrer sans mon PIN -> problème. Néanmoins, pour que ça fonctionne, il faut garder la clé publique... privée (car toute personne en sa possession pourra chiffrer un fake known_hosts), ce qui va à l'encontre du principe de Kerckhoffs (seule la partie privée doit être considérée comme secrète, tout le reste (algo, partie publique) doit être considéré d'office comme étant public ! ) et est donc une idée à oublier tout de suite.


Pour les autres usages de  la Yubikey, notamment l'OTP (pour PAM, site web, ...), voir https://numaparis.ubicast.tv/videos/pses-yubikey/ . On peut aussi l'utiliser avec LUKS.