Le mot de passe : Pourquoi, comment ?

On entend tout et son contraire au sujet des mots de passe et de leur gestion, en informatique. Alors je vais tenter de faire le point, en prenant tour à tour le point de vue de l’utilisateur, et du développeur en charge de la sécurité d’une application.

Côté utilisateur

Pourquoi un mot de passe ?

Un mot de passe est un élément d’authentification. Il s’agit d’une donnée secrète, normalement connue d’une seule personne. Pour vérifier qu’un interlocuteur est légitime, on vérifie s’il connaît ce secret partagé. Naturellement, dans une utilisation aussi simpliste (on ne parle même pas d’informatique), il apparaît naturellement que, lorsque l’on « prouve » son identité en fournissant le mot de passe, on n’est plus le seul à le connaître. Et que donc, si on l’utilise auprès de plusieurs tiers, ceux-ci peuvent se faire facilement passer pour nous. Si cela est possible, la sécurité apportée par le mot de passe est totalement compromise.

Faiblesses

On pense alors naturellement à utiliser un mot de passe différent pour chaque interlocuteur. Ça a du sens : si je m’authentifie avec un mot de passe a auprès de Alpha, mais que je n’utilise a nulle part ailleurs, Alpha n’aura que faire de ce mot de passe. Il ne pourra se compromettre que lui-même. Il est donc important de nepas réutiliser un mot de passe.

Réutilisation de
mot de passe — XKCD

Un mot de passe est censé être un secret. Donc pas devinable. Pour cela, il faut évidemment qu’il ne soit pas « logique ». Il est malheureusement plus que courant que des utilisateurs choisissent comme mot de passe leur date de naissance, le nom de leur poney, ou bien les premières lettres de leur clavier (quand ce n’est pas tout simplement « password » ou « 0000 »). Du coup, si je cherche à deviner le mot de passe de quelqu’un, j’ai tout à gagner à essayer ces combinaisons-là. Et ne vous dites pas « pas grave, j’ai mis une majuscule dans le nom de mon chien », ou « j’ai rajouté 007 à ma date de naissance », car cette attaque, appelée bruteforce, permet d’essayer des centaines milliers de combinaisons par seconde, et ce sans grand effort. Proscrivez impérativement les mots de passe simples à deviner.

Comment ?

Comment, alors, générer un mot de passe suffisamment robuste pour garantir un niveau de sécurité minimal ? Il y a plusieurs possibilités :

  • utiliser un générateur aléatoire. Il en existe une floppée en ligne, mais n’oubliez pas que si vous acceptez un mot de passe généré par une page web, vous n’êtes pas seul à le connaître. Cela s’apparente à de la paranoïa, mais c’est rarement une bonne idée de faire courir un risque à son mot de passe dès sa génération. Il existe cependant des logiciels libres (dont le comportement est donc vérifiable) qui proposent de telles fonctionnalités. Par exemple, Keepassx, en plus de sa fonctionnalité principale que je détaillerai plus bas, dispose d’un certain nombres de possibilités pour générer un mot de passe.
  • utiliser un mot de passe principal, modifié pour chaque usage. C’est à dire que chaque site utilisera un mot de passe différent, mais qu’à partir du mot de passe principal et d’une donnée en relation avec le site, vous serez capable de retrouver le mot de passe particulier. Mettons par exemple que vous ayiez un compte sur site example.org, et que votre mot de passe principal est « pinkiepieisthebestpony » (on se refait pas…). Le mot de passe pour ce site pourrait être, par exemple, « peixnakmipelpei.eoirsgtehxeabmepsltep.oonry », soit le mix des deux noms, en répétant si besoin le nom du site, et à raison d’une alternance d’une lettre à l’autre. Si vous vous contentez de concaténer les deux valeurs, si un mot de passe vient à être connu (et vous n’avez pas à faire confiance en un site), il sera aisé de comprendre quel est le mot de passe principal, et toute votre sécurité est compromise.
  • utiliser une dérivation de la méthode principale : vous avez un mot de passe principal et un nom de site. La différence est que vous allez rendre illisible le résultat, en le hachant par exemple. Pour ce faire, passez le mot de passe dans un algorithme de hachage (sous GNU/Linux, il y a ça sur à peu près tous les systèmes : il suffit de taper echo <mot de passe> | sha1sum, et vous obtenez une chaîne identifiant votre mot de passe. Je couvrirai le principe du hachage dans la deuxième partie du billet. Mais ainsi, aucune partie du mot de passe principal n’est envoyée au site. L’inconvénient est évidemment qu’il faut avoir l’utilitaire de hachage choisi sous la main (il est bien évidemment proscrit d’utiliser un service en ligne pour ça, car votre mot de passe n’a pas à sortir de votre machine en clair).

Une autre implémentation de cette solution m’a été indiquée : il s’agit d’une simple page HTML, que vous pouvez (et devriez) copier en local avant de l’utiliser. Ensuite, à partir d’un mot de passe principal et un nom de site/service, un mot de passe unique sera généré. utiliser d’autres méthodes d’authentification, lorsque cela est possible. Par exemple, si vous utilisez ssh, il est possible de s’authentifier par le biais d’une clé DSA/RSA, ce qui est une méthode par la possession, en opposition avec une méthode par le connu*. En clair, un serveur disposant de votre clé publique ne peut pas la réutiliser pour se faire passer pour vous, vu qu’il ne s’agit pas d’un secret partagé.

Mieux que le mot de passe : la phrase de passe

Phrase de
passe — XKCD

Sémantiquement, une phrase est une suite de mots. C’est cela dont il s’agit. Mais pas une suite de mots de passe, tels que « 6fQuhYP4EC EB9bWpLy78 6XcMGS5Y2P ». Une suite de mots courants de votre langue maternelle. Supposons une liste de 1750 mots courants français , dans laquelle on piochera quelques mots totalement au hasard. 5 mots peuvent suffire. Par exemple, ceux-ci :

nain, jambon, debout, désordre, mouchoir

Je le répète, il est crucial de choisir au hasard ces mots. On a sinon tendance à penser à des mots inspirés par notre environnement direct, et il suffit alors de connaître cet environnement pour deviner les mots possibles. Ici, les mots sélectionnés n’ont strictement aucun lien. D’un point de vue statistique, on a donc 1750^5 possibilités pour générer une phrase de passe par la méthode décrite. Mais le plus important est la possibilité de la remémorer. Car il est difficile, et il n’y a aucun moyen intelligent de retenir un mot de passe. Mais une phrase composée de mots courants peut être facilement mémorisée. Par exemple, imaginons une situation pouvant expliquer ces choix de mots :

un nain mange du jambon debout car c’est le désordre, et il n’a pas de mouchoir

Vous avez déjà retenu cette phrase de passe. Et elle est raisonnablement solide. Pour donner une idée de grandeur, avec 9 caractères alphanumériques contenant des majuscules, on a moins de possibilités (58^9). Et la complexité de mémorisation est incomparable.

Le problème avec cette solution est le besoin d’aléa. Elle n’est efficace que si les mots n’ont réellement aucun rapport, et la majorité des gens à qui on demande ça piocheront invariablement dans leur environnement.

Autres méthodes d’authentification

J’ai volontairement ici fait l’impasse sur les autres méthodes d’authentification, par exemple basées sur les tokens ou clés asymétriques. Non pas qu’il s’agisse de mauvaises solutions, bien au contraire, mais le seul thème des mots de passe est suffisamment complexe et intéressant à traiter.

Il faut également garder en tête un principe simple : c’est un être humain que l’on cherche à authentifier. C’est à dire qu’à partir d’un certain niveau de robustesse du mot de passe, le maillon faible devient évidemment l’utilisateur, et on ne peut pas l’améliorer informatiquement (sauf en le transformant en cyborg, mais ça mériterait de donner lieu à un autre billet).

Le mythe de la sécurité
— XKCD

Qu’en faire ?

On le dira toujours : on n’écrit pas un mot de passe. Ni sur un post-it collé sur son écran, ni sous son clavier, ni même dans un fichier ~/.keywords (ou autre). Mais naturellement, lorsque l’on est amené à connaître un grand nombre de mots de passe, il devient impératif de trouver une solution, sous peine de réutiliser les mots de passe ou de les rendre trop simples à découvrir, parce que ce sera naturel de ne pas perdre 10 minutes à se remémorer le moindre mot de passe.

Quoi qu’on en dise, il peut donc être justifié de noter ses mots de passe. Mais certainement pas en clair. Il existe plusieurs possibilités de bases chiffrées, comme par exemple la fonctionnalité de mot de passe principal de Firefox répond à ce besoin : les fichiers enregistrés dans le navigateur sont naturellement écrits sur le disque, mais sous une forme chiffrée par un mot de passe principal qui, lui, doit être retenu par l’utilisateur. Une autre possibilité est Keepassx, dont je parlais plus haut. Il s’agit d’un logiciel libre et interopérable, proposant les options qu’on s’attend de voir avec un tel logiciel. Quelques précautions de base s’imposent :

  • Ne mettez pas tous vos œufs dans le même panier. Faites en sorte qu’un fichier de mots de passe compromis ne puisse porter préjudice qu’à une chose.
  • Ne stockez que les mots de passe que vous ne pouvez pas retenir (faites un effort).
  • Ne lésinez pas sur la sûreté du mot de passe principal. Keepassx permet d’utiliser une clé (sous forme de fichier), un mot de passe, ou… les deux. Préférez les deux, il s’agira d’une authentification forte, et il est généralement préférable d’en avoir pour protéger des mots de passe. La clé ne doit pas se trouver à côté du conteneur (elle devrait rester avec vous et non sur la machine), et le mot de passe doit évidemment être robuste.
  • Et le plus important : les clés sont présentes en clair en mémoire lorsque le conteneur est ouvert. Donc refermez-le immédiatement après usage.

Côté développeur

Pourquoi un mot de passe ?

Un mot de passe est un élément d’authentification. Il s’agit d’une donnée secrète, normalement connue d’une seule personne. Pour vérifier qu’un interlocuteur est légitime, on vérifie s’il connaît ce secret. Naturellement, dans une utilisation aussi simpliste (on ne parle même pas d’informatique), il apparaît naturellement que, lorsqu’un utilisateur nous « prouve » son identité en fournissant son mot de passe, on le connaît aussi. Ce « on » peut être un site web, une société, bref plusieurs personnes peuvent avoir accès aux données. Et on a la responsabilité vis-à-vis de l’utilisateur de protéger son élément d’authentification.

Premièrement

On n’enregistre jamais le mot de passe d’un utilisateur en clair. Jamais jamais. Vraiment. Parce qu’il suffit de jeter un œil à la base de données, d’une façon ou d’une autre (par une intrusion informatique, ou par l’action d’un employé malveillant). Tout ce dont on a besoin est de pouvoir vérifier que le mot de passe d’un utilisateur est correct. Cela ne requiert pas nécessairement d’avoir soi-même le mot de passe pour le comparer.

Chiffrer ?

La cryptographie, l’art de rendre un message illisible à quiconque ne lui est pas destiné, c’est très bien. Mais chiffrer les mots de passe des utilisateurs avant de les stocker en base de données n’est pas une bonne idée. Car, si on doit pouvoir comparer le mot de passe, le destinataire du message se retrouve être l’application web qui l’a elle-même chiffrée. On retrouve alors le même problème : quiconque a accès à l’application peut déchiffrer facilement les mots de passe. En réalité, il faut qu’il soit impossible de retrouver les mots de passe.

Hacher

Il existe des fonctions cryptographiques qui permettent de générer des sommes de contrôle, des chaînes raisonnablement uniques construites à partir d’un message, ne permettant théoriquement pas de retrouver le message d’origine. Ainsi, deux chaînes proches génèrent deux empreintes parfaitement différentes. On peut se servir de ce principe pour ne stocker en base de données que les empreintes des mots de passe des utilisateurs. Lorsque quelqu’un tente de s’authentifier, il envoie son mot de passe, et notre application en génère l’empreinte, puis compare les deux empreintes. Si elles sont identiques, l’authentification est validée.

La fonction de hachage la plus connue est sans doute le MD5. Ne l’utilisez pas. Il est bien trop faible, et il est aujourd’hui facile, par le biais de tables de correspondances, de retrouver une chaîne capable de générer une empreinte donnée. Il y a bien d’autres algorithmes plus fiables. Nous verrons cela plus tard.

Saler

Il existe, pour les algorithmes courants (essentiellement md5 et sha1), des rainbow tables, fichiers contentant de grandes quantités d’empreintes, associées à la chaîne hachée. Ainsi, même avec les mots de passe hachés en base, il est parfois possible (notamment lorsque les utilisateurs ont de mauvaises habitudes d’utilisation de mots de passe) de retrouver un mot de passe à partir de son empreinte. Pour cela, on va ajouter un grain de sel, rendant l’empreinte plus unique. Concrètement, il s’agit d’un élément rajouté au mot de passe avant de le hacher. On peut par exemple définir une chaîne aléatoire, stockée en clair dans notre application (à un autre endroit que la base de données), qui sera ajoutée à la fin de chaque mot de passe avant qu’il passe à la moulinette du hachoir. Si notre sel est suffisamment grand et aléatoire, il a peu de chances d’être présent dans les rainbow tables.

Autre problème : peu importe l’algorithme, son principe est de générer une empreinte unique pour une chaîne donnée. Par conséquent, si deux utilisateurs utilisent par hasard le même mot de passe, leur empreinte sera la même. Ce qui n’est pas un dysfonctionnement de l’application, mais permet à un attaquant d’en déduire que les deux utilisateurs possèdent le même mot de passe. Si par hasard (et avec un peu de volonté et de patience), il s’avère que l’un des utilisateurs a écrit son mot de passe sur un post-it sur son écran, ou plus probablement s’il tombe dans le piège d’un mail de phishing, il est alors trivial de compromettre le second. Il est alors important d’ajouter un niveau de sécurité au stockage des mots de passe de notre application.

Ce dernier problème est lié au fait que notre sel est statique : on utilise le même pour tous les utilisateurs, donc on ne se prémunit pas de mots de passe identiques. Il faut alors rendre le sel dynamique, autrement dit d’en utiliser un différent pour chaque utilisateur. On peut par exemple utiliser l’identifiant unique d’un utilisateur comme base de sel (car un identifiant seul est trop court). Utilisons donc l’empreinte de l’identifiant, comme sel pour générer l’empreinte du mot de passe. Tous nos mots de passe seront donc bien différents en base. On a fini ?

Non.

Le sel est alors assez faible, car devinable (il s’agit de l’empreinte d’un identifiant numérique probablement auto-incrémenté, et parfois connu de tous les utilisateurs, si par exemple on l’utilise dans les URL. En gardant l’idée d’utiliser un sel dynamique, on peut le générer nous-mêmes, de façon pseudo-aléatoire. Il convient ensuite de le stocker, évidemment, sinon nous ne pourrons pas vérifier ultérieurement le mot de passe. Donc on a un sel, enregistré à côté de l’empreinte. Si ces données sont compromises, il n’est normalement pas possible (sauf faiblesse dans l’algorithme) de revenir au mot de passe initial à partir de ces éléments. À ce niveau-là, on a une sécurité acceptable pour notre application. Voyons jusqu’où on peut monter, et quels en sont les coûts.

Aller plus hauuuut ♫

Au stade où nous en sommes, il est toujours possible, si l’on parvient à récupérer les informations en base de données, d’attaquer sauvagement l’empreinte au bruteforce. Je répète le principe : on teste toutes les chaînes possibles avec cet algorithme, en y ajoutant le sel, jusqu’à ce que ça passe. Il est possible d’handicaper très sérieusement cette attaque : en utilisant une fonction de hachage lente. Car, si pour une application, on cherche à obtenir le meilleurs temps de réponse possible, l’étape d’authentification est normalement unique par session, et il ne s’agit pas d’une étape qui nécessite une grande réactivité. D’un autre côté, rendre plus lent le calcul d’une empreinte peut passer inaperçu auprès de notre utilisateur, tandis qu’un attaquant qui cherche à tester des millions de chaînes mettra beaucoup plus de temps à réaliser son attaque. Pour cela, on peut utiliser l’algorithme scrypt, auquel on peut demander de passer un temps donné sur le calcul d’une empreinte, ce qui fera différer celle-ci. Attention : scrypt est le nom de deux applications séparées : un utilitaire de chiffrement symétrique, et un algorithme de dérivation de clé. C’est ce dernier qui nous intéresse. Il faut également savoir que scrypt n’est pas présent par défaut dans tous les langages. Par exemple en python, il vous faudra installer (via pip) scrypt). Avec une durée d’exécution nettement supérieure aux autres méthodes, celle-ci est raisonnablement résistante au bruteforce.

Attention toutefois. L’utilisation de cet algorithme passe par un module tiers. Donc pas forcément validé par des experts. Et récupéré, via pip, en http en clair. Il n’y a donc pas de certification au sujet de ce code. Vous devez donc, avant de l’utiliser, vous assurer par vos propres moyens que ce module est digne de confiance.

Encore un peu ?

L’état de l’art consiste maintenant à isoler la partie de vérification du mot de passe, de façon matérielle si possible, en utilisant un HSM. On peut toutefois, et pour une sécurité moins bonne, opter pour une isolation logicielle, par exemple en désignant une machine virtuelle isolée du réseau, et accessible uniquement depuis notre application, qui sera seule à pouvoir traiter l’authentification. Ainsi, si notre application est compromise, la partie authentification est intacte, et les empreintes ne sont même pas connues (sauf compromission totale de l’infrastructure, évidemment, donc il ne faut pas négliger une bonne gestion des données confidentielles), même au sein d’un tel module.

Trop c’est trop ?

Sachez rester en terrain connu. Vous n’êtes pas un expert reconnu en cryptographie, alors n’inventez pas la roue. Ne vous dites jamais que jouer au petit chimiste et piocher ça et là des algorithmes que vous appliquerez les uns au-dessus des autres renforcera votre code, car c’est l’inverse qui se passera : vous ne saurez pas ce que vous faites, et il ne s’agira certainement pas d’une recommandation sérieuse de sécurité.

De la même façon, n’essayez jamais de créer votre algorithme de sécurité. Faites-le pour rire dans votre coin si vous voulez, mais ne vous amusez en aucun cas à l’utiliser en production, tant qu’il ne s’agira pas d’un standard reconnu.

Conclusion

Le mot de passe est une donnée critique dans un Système Informatique, et doit être traité en connaissance de cause. Il n’est pas nécessaire d’être un expert pour respecter les bons usages, il faut simplement qu’ils soient connus. Pour finir, je vous conseille un billet qui traite du même sujet en plus technique, en abordant d’autres points de vue.

Les images de utilisés sont l’œuvre de Randall Munroe, et sont publiées sous licence CC-by-nc sur XKCD.

Merci à Geoffroy Couprie, Skhaen, Rogdham et Progval pour la relecture et les ressources