Authentification client serveur

Un article de Le wiki de 2 noisettes - noisette.ch.

Sommaire

Introduction

Le problème de l'authentification d'un client auprès d'un serveur peut être facilement résolu par des primitives cryptographiques comme les paires de clés publiques/privées (PK), les clés symmétriques de sessions et les protocoles challenge/response. Le problème inverse, l'authentification du serveur auprès du client, est lui aussi très bien résolu avec les certificats et les signatures des autorités de certifications (CA).

Néamoins, dans les applications légères où on ne veut déployer ni une CA ni une PKI (infrastructure de gestion des PK), le problème reste complexe à traiter.

On a observé récemment une augmentation des virus et vers qui modifient les fichiers hosts (/etc/hosts ou c:\windows\system32\drivers\etc\hosts) afin de pouvoir tromper l'utilisateur et l'envoyer vers une copie du site qu'il pensait atteindre.

Client peu sûr

L'hypothèse qui prévaut dans cet exemple est donc que toutes les informations stockées chez le client peuvent être modifiées. On part ainsi du principe que la copie locale du certificat serveur, utilisé par le client pour authentifier sûrement le serveur qu'il contacte, peut être modifiée et donc ne pas émettre d'avertissement en cas de contact d'un faux serveur.

L'idée est donc de spécifier un protocole d'authentification mutuelle forte entre un client et un serveur : le client sera sûr de parler au bon serveur, et le serveur aura authentifier le client, le tout avec un seul secret commun : le mot de passe du client.

Les méthodes cryptographiques utilisées resteront des fonctions classiques comme SSL, AES, ..., car elles sont éprouvées.

Prérequis

Le serveur dispose d'un certificat permettant l'étblissement d'une connexion sécurisée avec un client (SSL par exemple). Il disposera en outre une paire nom d'utilisateur/hash du mot de passe du client, auparavant établi et échangé de manière sûr.

Protocole


Une fois une connexion sécurisée quelconque (SSL) établie entre le client et le serveur, le protocole d'authentification mutuelle commence :

  1. Après avoir demandé à l'utilisateur d'entrer son nom d'utilisateur et son mot de passe dans des champs correspondants, le client envoie son nom d'utilisateur au serveur, ainsi qu'une valeur aléatoire qui fait office de challenge.
  2. Ce dernier ressort de sa base client le hash du mot de passe, et encrypte le challange avec ce hash. Il envoie au client le resultat de cette encryption ainsi qu'une autre valeur aléatoire, qui est le challange du client.
  3. Le client décrypte la réponse du serveur et le compare avec la valeur envoyée. Si les 2 concordent, le client est alors sûr de parler au bon serveur et peut donc encrypter le challange du serveur avec le hash de son mot de passe et retourner le tout au serveur.
  4. Le serveur reçoit le hash du client, et le compare avec la valeur de sa base client. Si les 2 correspondent, le client est alors identifié sûrement.

Image:Protocole authentification.png

Note : la première version du protocole, où le serveur envoyait son certificat crypté au client, était vulnérable à une replay attack : une personne mal attentionnée qui sniffait le réseau pouvait, lors de la prochaine authentification du client, émuler le serveur en envoyant le certificat encrypté entendu sur le réseau. Le client n'aurait rien vu et aurait envoyé son hash au faux serveur.

Conclusion

Ce protocole d'authentification mutuelle est très pratique dans les cas où une infrastructure légère est requise. Néamoins, la base client du serveur ne doit à aucun moment être compromise. Faute de quoi un autre serveur pourra prendre ce rôle.

Note : ce schéma n'est pas résistant à une attaque de type "man-in-the-middle", type d'attaque impossible à parer sans avoir de secret partagés. Un autre problème rencontré (duquel découle l'attaque précédente en fait) et l'information leakage dont est victime le client qui révèle son nom d'utilisateur. A corriger donc.

Pour la correction, une première idée serait d'inverser les roles d'identification (donc 1 : le serveur, 2 : le client) et d'envoyer un token contenant le nom du client hashé avec le challenge, mais le serveur devrait tester la correspondance avec tous les clients de la base pour retrouver la correspondance, ce qui est peu performant si la base contient beaucoup de clients.

Image:Protocole authentification mitm attack.png