Implémentations de la phrase de passe

Vous gérez un service web, un site web, un logiciel et vous voulez implémenter une gestion de mots de passe pour vos sessions utilisateurs ?

Posté le
(Dernière modification le )
8 minutes
1699 mots

Lisez d’abord cet article sur ce qu’est un bon mot de passe puis continuez la lecture de celui-ci.

Règles de mot de passe

Si vous êtes tenté de mettre des règles de mot de passe du genre « entre 8 et 20 caractères » ou « 3 majuscules », arrêtez tout.

Cette façon de procéder est obsolète, hyper rigide pour l’utilisateur et le conduit à créer des mots de passe compliqués pour lui et très faciles à percer pour un Bot.

Vous ne me croyez pas ? Regardez le compte Twitter de passwordistoostrong (en anglais).

Un exemple :

Imaginons la règle :

« entre 8 et 20 caractères, au moins 3 majuscules et un signe de ponctuation. »

Ce mot de passe correspond : « AbCdEfgh! » bien qu’il ne puisse pas être considéré comme fort.

Par contre, l’utilisateur peut être frustré.

Entropie

Utilisez plutôt un système basé sur l’entropie.

La bibliothèque zxcvbn (ce sont les lettres de la ligne du bas d’un clavier américain) est une bonne implémentation du calcul de la force d’un mot de passe par entropie. Elle est accessible dans une grande variété de langages informatiques. C’est celle que nous utilisons chez Limawi.

L’avantage est qu’il n’y a plus de règles rigides pour l’estimation de la force du mot de passe. La bibliothèque calcule la complexité de votre mot de passe (en prenant en compte la rareté des lettres, de leurs agencements, etc.) et lui donne une note. Vous pouvez ensuite définir à partir de quelle note, quel cap, vous considérez le mot de passe entré comme suffisamment sûr.

Vous devez, bien sûr, avoir les mêmes notes, les mêmes caps, côté serveur et côté client. En cas de différence, c’est le serveur qui a le dernier mot car le côté client peut être trafiqué par un hackeur (son environnement n’est pas sûr).

Éviter les mots de passe percés

Une fois que vous avez mis un cap pour éviter les mots de passe faibles, il faut quand même vérifier si le mot de passe saisi n’est pas un mot de passe qui a déjà été percé.

Cette étape est une sécurité supplémentaire optionnelle car si le cap de complexité est assez haut, la façon dont le mot de passe est stocké peut contrer les attaques arc-en-ciel de façon relativement efficace. Mais c’est quand même un bonus.

Pour cela, on peut charger un fichier javascript côté client ou faire une requête ajax sur une API quand l’utilisateur crée son mot de passe.

Si votre requête Ajax envoie le texte en clair, c’est problématique, car vous offrez une surface d’attaque supplémentaire aux hackeurs.

Le fichier javascript chargé est lourd et il vaut mieux le charger en asynchrone. Mais, même en asynchrone, la taille du fichier (et donc le nombre de mots de passe) ne peut pas être élevé.

Bien sûr, le côté client n’étant pas sûr, il faut réitérer l’opération côté serveur.

Une autre technique consiste à utiliser le service Have I Been Pwned. Il offre une solution élégante d’un point de vue technique mais étant de droit australien et reposant sur des services américains, il pose une sérieuse question concernant le respect du RGPD européen (voir dans un futur article sur notre site).

Ce service fonctionne grâce au k-knowledge (connaissance-k ?).

Vous hachez le mot de passe saisi par l’utilisateur et vous envoyez au service les k premières lettres de ce hash. Le service vous renvoie tout les hashes de sa base de données qui ont ces k premières lettres. Vous comparez avec le hash du mot de passe de l’utilisateur et, si un des hashes du service correspond, alors c’est que le mot de passe est percé.

Exemple :

le mot de passe « framboise » a pour hash SHA256 :

« F9E4141EE43A3B877758E2584A1F6A0E7A9C8D6E58BB859A1665D8C1F447003C »

les 5 premières lettres sont « F9E41 ».

Vous envoyez ces 5 lettres à Have I Been Pwned.

Il renvoie :

  • « F9E4141EE43A3B8777ERT8584A1F6A0E7A9C8D6E58BB859A1665D8C1F447003C »
  • « F9E4141EE962758777ERT8584A1F6A0E7A9C8D6E58BB859A1665D8C1F447003C »
  • « F9E4141EE43A3B877758E2584A1F6A0E7A9C8D6E58BB859A1665D8C1F447003C »

Vous comparez et vous vous rendez compte que le troisième hash est le même que celui du mot de passe. Le mot de passe est donc percé.

Avec ce système, aucun mot de passe ne circule sur le réseau et Have I Been Pwned ne sait pas quel mot de passe vous avez testés. Pour l’exemple, trois résultats ont été renvoyés mais plus k est petit, plus le nombre de résultats renvoyé est grand.

Puis stocker vos mots de passe

Ensuite, une fois que l’utilisateur a trouvé un bon mot de passe, il vous l’envoie (de façon sécurisée) et vous devez le stocker.

Alors, une règle tout à fait fondamentale : ne stockez jamais un mot de passe en clair. Si un hackeur réussit à accéder à votre stock de mots de passe, vous lui avez servi, sur un plateau, l’accès à la totalité des comptes sur votre service et à d’autres services (les utilisateurs réutilisent souvent malheureusement le même mot de passe sur des services différents).

Alors comment faire ?

  1. Tout d’abord, il faut que vous limitiez la longueur du mot de passe mais pas trop. Drupal, par exemple, limite la longueur a 512 octets, c’est à dire entre 512 et 128 caractères en UTF-8. Cette étape est nécessaire pour éviter une attaque DOS car l’étape de hash demande un peu de ressource machine (on saisit un énorme mot de passe de plusieurs milliers de caractères qui bloque la machine à l’étape de hash.).

  2. Ensuite, vous générez aléatoirement un sel (sel de table appelé plus communément poivre ou sel de ligne ?). C’est à dire une chaîne d’un nombre précis de caractères.

    Sel de table aussi appelé poivre

    Sel de table

    Sel de table aussi appelé poivre
    Vous pouvez le générer au niveau de votre stock (c’est à dire pour tout le stock) ou au niveau du mot de passe (un par mot de passe). Il sera ajouté au mot de passe pour rendre deux mêmes mots de passe différents. Le sel sert à empêcher les comparaisons de hash, table par table ou ligne par ligne, si un utilisateur a utilisé le même mot de passe sur plusieurs services différents ou si deux utilisateurs ont choisi le même mot de passe.

    Exemple :

    Avec un sel par table :

    Alice a mis le mot de passe « framboise » dans le site « gentilles-framboises-aplaties.com » et dans le site « méchantes-framboises-aplaties.com ».

    Le site « gentilles-framboises-aplaties.com » génère le sel « 458 », le mot de passe de Alice sera donc « 458framboise ».

    Le site « méchantes-framboises-aplaties.com » génère le sel « gdf », le mot de passe de Alice sera donc « gdfframboise ».

    Si un hackeur réussit à capturer les deux tables, il ne pourra pas comparer les hashs des mots de passe car ils seront différents (puisque les mots de passe sont différents). Il ne saura pas que Alice a mis le même mot de passe sur les deux services.

    Avec un sel par ligne :

    Alice a mis le mot de passe « framboise » dans le site « gentilles-framboises-aplaties.com », Bob a mis aussi le mot de passe « framboise » dans le même site.

    Le site « gentilles-framboises-aplaties.com » génère le sel « 458 » pour le mot de passe d’Alice, le mot de passe de Alice sera donc « 458framboise ».

    Le même site génère le sel « sdd » pour le mot de passe de Bob, le mot de passe de Bob sera donc « sddframboise ».

    Dans ce cas, un hackeur qui réussit à avoir la table du site « gentilles-framboises-aplaties.com » ne pourra pas comparer le hash de Bob et celui d’Alice. Il ne saura pas que c’est, en fait, le même mot de passe.

  3. Ensuite vous hachez votre chaîne de caractères composée du sel et du mot de passe. Utilisez un algorithme sûr comme SHA512 par exemple.

    Le hash résultant pour le mot de passe « framboise » et le sel « 458 » est :

    hash(sha256, ‘458framboise’) = ‘527D88733ED03CE5EF2D12AE4279950ABC29DC42817B14A58AB2150678A7CC72486CE637B8AD10333E80879F3D0CE685FA6CBB5DB8D7954382C2116616F8F6CF’

  4. Vous avez déjà un mot de passe a peu prés sécurisé stocké. N’oubliez pas de stocker aussi le sel. Vous pouvez renforcer le hash en répétant la dernière étape avec le hash précédant, à la place du sel :

    hash(sha256, ‘527D88733ED03CE5EF2D12AE4279950ABC29DC42817B14A58AB2150678A7CC72486CE637B8AD10333E80879F3D0CE685FA6CBB5DB8D7954382C2116616F8F6CF framboise’) = ‘E3A252D3C455D638C82D8430DDC85E9B5B13F6508D690D97E2C5A1CC8AEE4A26D4C723E4EE4F524B4926C0357B2651132DF67446721BB4D3BCDD017C4A0E0E1B’

    Le but est d’éloigner le hash résultant de possibles hashes déjà connus par les hackeurs. Il faut que ce soit compliqué pour eux de retrouver le mot de passe.

    Une fois votre mot de passe stocké, quand l’utilisateur veut se reconnecter, votre système refait les mêmes étapes (en utilisant le sel déjà existant) et compare le résultat obtenu avec le hash déjà présent dans le stockage. Si ce sont les mêmes, c’est le bon mot de passe.

Les erreurs à éviter

Des fois, on fait des erreurs tellement bêtes ! En voici quelques unes à éviter.

Quand vous changez le cap de complexité des mots de passe acceptés, ne mettez pas ce seuil dans les champs d’anciens mots de passe. Sinon l’utilisateur ne pourra plus saisir son ancien mot de passe pour le changer. Mettez le cap de complexité uniquement sur les champs de nouveaux mots de passe.

Si vous changez la façon dont vous stockez vos mots de passe ou la complexité et vous avez besoin que l’utilisateur agisse, signalez le lui par email. N’envoyez pas de récupération de mot de passe avec lien unique, l’utilisateur peut très bien le lire des mois après, le temps pour un attaquant de l’utiliser.

N’envoyez, bien sûr, jamais le mot de passe d’un utilisateur par email. Retenez que les emails sont comme des cartes postales : tout le monde peut les lire. Et si vous arrivez à envoyer son mot de passe à un utilisateur, cela veut dire que vous ne le stockez pas correctement.

Faites des messages d’erreur signifiants quand l’utilisateur crée un nouveau mot de passe. Donnez des valeurs comme « faible, fort, très fort » et pas des notes d’entropies incompréhensibles.

Bien sûr, assurez-vous que le mot de passe est bien envoyé via une connexion https. Bannissez http de votre système.

Pour allez plus loin, faites des chaînes d’authentification. C’est à dire de la double authentification avec un token sur un smartphone par exemple, en plus du mot de passe.