Keydoo

De Wikidroids

Sommaire

Objectif

Fabriquer un appareil de petite taille (style clé USB) permettant de se logguer en ssh depuis un poste considéré comme non sûr vers un poste sécurisé, sans crainte d'un vol de mot de passe ou de session.

Cahier des charges

  • La machine cliente peut comporter toute sorte de spyware, keylogger mais ne devra pas pouvoir acceder aux données tranférées du clavier local vers le terminal de la machine sécurisé.
  • On considère le clavier comme sûr, c'est une hypothèse de départ. Comme il existe des claviers transportables, on peut considérer que l'utilisateur paranoïaque² peut fournit son clavier.
  • Impossibilité pour la machine cliente de rejouer une séquence pour se relogguer ou pour réemettre les mêmes commandes.
  • Empêcher d'exploiter une session qui aurait été volée par un client ssh malveillant.

Fonctionnement

Token.png

A tout moment, chaque frappe d'une touche au clavier provoque le clignotement d'une LED (ou mieux, la modification d'un compteur sur le LCD).

  • allumer le token et entrer le code pin (une molette-bouton serait parfaite, pas besoin de clavier). S'il est correct, le token passe en mode bypass (tout ce qui est tapé est recopié). S'il est faux 3 fois de suite, la clé secrète est effacée de l'EEPROM.
  • Brancher le clavier sur le token et le token sur l'ordi. Lancer un terminal, puis un client ssh : 'ssh login:skey@host'. Le serveur demande un password.
  • Une sequence d'echapement permet de passer en mode "init" (par exemple un double-clic sur la touche ALT). Les touches tapées au clavier ne sont plus forwardées mais servent à commander le menu LCD.
  • Entrer le numéro du one-time password. Le token calcule alors le mot de passe et l'envoie au PC au moment où l'utilisateur valide le numéro.
  • La première ligne affichée par serveur après login correspond à la valeur du compteur pour le chiffrement. Taper ce nombre au clavier, puis entrée. Ceci a pour effet d'initialiser le l'algo de chiffrement, et de passer le clavier en mode chiffré.
  • A ce moment, le token chiffre chaque frappe clavier. Le shell de login utilisé côté serveur est capable de déchiffrer ces touches avant de les envoyer au véritable shell. On peut également imaginer d'envoyer en plus un peu de bruit (qui sera éliminé par le programme coté serveur) afin d'empêcher la machine locale de faire des supositions sur les commandes tapées (un "ls" est peut-être reconnaissable ?)
  • Une sequence d'echapement permet de switcher entre le mode "bypass" et le mode "chiffré" (par exemple un double clic sur CTRL).

Planning

Voici les tâches (j'aurais préféré utiliser le terme milestones, jalons, ou tout autre expression de manager) du projet. Certaines tâches peuvent s'effectuer en parallèle.

  • Code pour générer le one-time password sur PC à partir de la clé secrète partagée.
  • Une fois validé sur PC, même code, mais pour AVR.
  • Code qui chiffrer un octet en un ensemble de caractère facilement tapable sur tout clavier (pas de caractère trop exotique), tournant sur PC.
  • Une fois validé sur PC, même code, mais pour AVR.
  • Code pour déchiffrer les caractères, sur PC uniquement.
  • Driver clavier, affichage des caractères tapés sur un terminal série, le driver doit prendre en compte la disposition du clavier.
  • Emulateur de clavier, les caractères tapés sur le terminal série sont envoyés à un PC (même remarque sur la disposition du clavier).
  • Convertisseur mapping clavier: afin de vérifier que l'assemblage entre le driver et l'émulateur fonctionne, on fait un code qui va convertir un mapping français en américain par exemple.
  • Assemblage de tous les développements en un seul prog, sur la carte de test.
  • Réalisation de la carte proto
  • Correction des problèmes info/elec


Code

Le code embarqué se base sur une version de développement d'Aversive, un framework contenant des bibliothèques pour les microcontrôleurs AVR.

Le code se trouve ici : Keydoo cvsweb

Protocole PS/2

D'abord, quelques liens intéressants :

Scancode

Emulation de terminal

Je suis tombé là dessus par hasard, je sais pas si ça servira, mais vu qu'on avait des pb de taille de terminal en utilisant le script python, ça peut peut-être aider à capter le pb. http://www.ohse.de/uwe/software/resize.c.html

Crypto

Aprés quelques lectures de rfc (rfc3686 entre autres) voilà une ébauche des mécanismes crypto au moment de la phase de login:

  • Le token génère un IV (64bits) et un Nonce (32bits).
  • Il les envoie au serveur en clair.
  • Une idée serait de les envoyer signés avec du hmac par exemple (avec une clef secrète générée au moment de l'initialisation du token sur le serveur)

Une fois l'initialisation de la connection effectuée, on peut chiffrer les touches en mode compteur (voir plus bas)

Remarques

  • Quid d'un client ssh modifié qui tenterait discrètement de demander au serveur le forwarding de port, ou tout autre feature proposé par ssh ?
    • On pourrait considérer que ce genre de features devrait être interdites sur le serveur. Avec les nouvelles directives Match d'OpenSSH, il sera peut-être possible d'activer des restrictions pour les utilisateurs qui se logguent avec le token.
  • Les touches avec modificateur (genre ctrl, shift) sont-elles plus complexes à traiter (en ps2 pour commencer)
  • Il faut assurer l'intégrité des données chiffrées par mode compteur (rappel: en mode compteur on a une valeur initiale, c'est ce compteur qu'on chiffre, et on XOR le texte avec ca): si l'attaquant connait la position de la touche dans le chiffré, il lui suffit de changer qq bits pour envoyer n'importe quoi.

idée rapide: on fait un HMAC (md5 par exemple) de la touche (en utilisant la clef partagée par exemple), le texte a chiffré a donc la forme :

 ___ 128bits ___ + ____ 128bits ____
 
 TOUCHE+RND+HMAC(TOUCHE+RND)

et le RND, c'est pour déconner... du coup on ferait de l'aes 256bits mode compteur. (en plus, c'est le mode préféré de pierre)

  • Ce qu'envoit un clavier au PC est une position de touche (le token fera la même chose). Le problème est que l'emplacement d'un 'a' par exemple est différent sur un clavier français et américain. D'autre part, il est difficile de pouvoir émettre n'importe quel caractère sur 8 bits depuis un clavier (quelle combinaison de touche pour envoyer 0xF1 ?). Une solution consisterait donc à avoir un mapping des claviers usuels dans le token, et de n'émettre que des touches valides sans caractères trop exotiques (clairement moins de 256). L'autre solution est d'envoyer la position de la touche en chiffré, et de décoder du coté du serveur. La première solution me paraît meilleure car il faut pouvoir générer la séquence de touche pour émettre le one-time password.
  • Si on est dans l'obligation d'utiliser un clavier douteux, il devrait être possible de modifier le mapping du clavier pour faire correspondre une touche avec une autre, ou bien d'ignorer une touche sur deux, ... ceci limiterait les conséquences d'un keylogger hardware dans le clavier.


Côté serveur:

  • le shell de l'utilisateur concerné par ce mécanisme de login aura un shell spécifique (par exemple sheba) décryptant l'entrée standard.
  • Les clefs secrètes seront stockées dans son home dans un répertoire spécifique (un peu à la manière du .ssh)
  • Ces clefs sont générées par le script d'initialisation du token lors de sa synchonisation.
  • Celui-ci contiendra les clefs secrètes permettant de chiffrer et de signer (en hmac) les données sensibles décrites ci-dessus
Boîte à outils
LANGUAGES