"En France, environ 60 % des notifications reçues par la CNIL depuis le début de l’année 2021 sont liées à du piratage et un grand nombre aurait pu être évité par le respect de bonnes pratiques en matière de mots de passe". Voici ce que nous dit la CNIL fin 2022. En effet les politiques de mots de passe sont encore trop souvent absentes ou trop permissives sur les applications web et pourtant si simple à mettre en place. Alors aujourd'hui je te donne toute les cartes pour choisir ta politique et la mettre en place avec seulement quelques lignes de code.
Au programme :
Les nouvelles recommandations de la CNIL
Comment calculer l'entropie d'un mot de passe ?
Qu'est ce qu'un dispositif de limitations des soumissions abusives ?
Tests
Quelles validations mettre en place dans nos modèles ?
Bonus : Comment Devise stocke les mots de passe
Nouveau : Le défi
Hello les petits Biscuits !
Bienvenus sur la 8ème édition de Ruby Biscuit.
Vous êtes maintenant 155 abonnés (ça fait chaud au cœur) 🥳 Et si vous n’êtes pas déjà inscrit :
Les nouvelles recommandations de la CNIL
Le 17 octobre 2022 la CNIL a publié de nouvelles recommandations concernant les politiques de mots de passe.
Voici les points qu'il faut retenir :
Ils recommandent de viser un degré de complexité du mot de passe, appelé entropie, plutôt que de viser une certaine longueur.
L’« entropie » peut être définie dans ce contexte comme la quantité de hasard. Pour un mot de passe ou une clé cryptographique, cela correspond à son degré d’imprédictibilité théorique, et donc à sa capacité de résistance à une attaque par force brute
Ils préconisent une entropie minimale de 80 bits lorsque l'authentification ne se base que sur un mot de passe.
Ils préconisent une entropie minimale de 50 bits lorsqu'un dispositif permettant de limiter les soumissions abusives est présent.
Essayons de déconstruire ces recommandations vagues en commençant par comprendre l'unité de mesure de l'entropie.
Le terme bit est une contraction de "binary digit". C'est une unité directement associée au système binaire qui ne peut prendre que deux valeurs : 0 et 1.
On emploie le bit comme unité de mesure de base de l'information. Il est important de ne pas le confondre avec le byte.
Le byte dit "baïte" est l'unité d'information correspondant à un octet, soit 8 bits.
Rubystiquement parlant : 8 bits == 1 byte
Retenez qu'un b minuscule représente un bit, un B majuscule le byte.
On parle aussi d'octet, qui n'est que la traduction en français de byte.
Comment calculer l'entropie d'un mot de passe ?
Pour un mot de passe à 12 caractères qui peut contenir 102 caractères possible (10 chiffres, 26 majuscules, 26 minuscules, 40 caractères spéciaux), le nombre de combinaisons possibles est 1268241794562545318301696.
Ensuite il suffit de convertir ce résultat en bits pour calculer son entropie. Pour ça nous avons besoin d'utiliser la fonction log2() et nous allons simplement faire log2(1268241794562545318301696) qui nous donne le résultat : 80.06910410365795, ce qui arrondi fait 80. Pour ceux qui ne sont pas familiers avec cette fonction, vous pourrez en apprendre davantage ici.
Pour le même résultat vous pouvez aussi faire le calcul suivant dans votre console :
$ Math::log2((10+26+26+40)**12)
=> 80.06910410365795
Si on se base sur le calcul précédent, concrètement :
Un mot de passe de 80 bits implique au choix :
12 caractères si le mot de passe utilise au moins 1 majuscule, 1 minuscule, 1 chiffre et un caractère spécial.
14 caractères si le mot de passe utilise au moins 1 majuscule et 1 minuscule
17 caractères si le mot de passe utilise uniquement des lettres minuscules
Un mot de passe de 50 bits implique au choix :
8 caractères si le mot de passe utilise au moins 1 majuscule, 1 minuscule, 1 chiffre et un caractère spécial.
9 caractères si le mot de passe utilise au moins 1 majuscule et 1 minuscule
11 caractères si le mot de passe utilise uniquement des lettres minuscules
Nous sommes bien d'accord qu'un mot de passe de 80 bits d'entropie est peu commode. Malgré le fait qu'il soit quasiment imprédictible pour un ordinateur, c'est très contraignant d'imposer de telles contraintes à nos utilisateurs, d'autant plus à l'inscription, ça pourrait les faire fuir ! Plus c'est simple, mieux c'est, c'est pourquoi nous préférerons partir sur la 2ème option de la CNIL en ajoutant un dispositif de limitation des soumissions abusives.
Qu'est ce qu'un dispositif de limitations des soumissions abusives ?
Une restriction d'accès est un mécanisme permettant à la plateforme de limiter les soumissions abusives. En d'autres termes, l'idée est ici de rendre impossible ou de complexifier la tâche aux hackers lorsqu'ils tentent de tester une infinité de mots de passe possibles (attaque par la force brute).
Il existe différentes possibilités pour cela :
Captcha : Le principe le plus classique où on vous demande de cliquer sur des photographies de bus ou de girafes. C'est relativement simple à mettre en place grâce à la gem Google ReCaptcha. en revanche je vous déconseille de l'utiliser car la CNIL le défini comme non conforme au RGPD. Il existe des alternatives conformes telles que Friendly Captcha mais ces solutions sont en général payantes.
Temporisation d'accès au compte après plusieurs échecs ou blocage du compte après X échecs : C'est-à-dire stocker sur le compte le nombre de tentatives échouées et le réinitialiser lors d'une connexion. Si vous utilisez la gem Devise, vous n'avez qu'à activer le module lockable et vous laisser guider par la documentation. Ensuite vous n'aurez qu'à définir quelle stratégie vous souhaitez adopter. Un déblocage du compte soit par un administrateur, soit automatiquement après un certain délai soit via un lien unique envoyé par mail.
Nombre maximal de tentatives autorisées dans un délai donné : Ce dispositif est plus compliqué à mettre en place car il va nécessiter des connaissances plus pointues du fonctionnement des requêtes HTTP. Une bonne solution pour mettre en place une telle limitation est d'utiliser la gem Rack-Attack même si l'idéal serait de pouvoir bloquer la requête directement avant qu'elle n'atteigne le serveur.
Nous avons vu les différentes options pour ajouter un dispositif de limitation des soumissions abusives, il ne nous reste plus qu'à implémenter notre politique de mot de passe. Nous allons faire en sorte qu'elle soit la moins contraignante possible tout en garantissant une entropie de 50 bits minimum.
Tests
Spoiler mais comme le veut la tradition… 👷
Quelles validations mettre en place dans nos modèles ?
Afin de s'assurer qu'aucun mot de passe avec moins de 50 bits d'entropie ne soit accepté, je vous propose d'utiliser un validateur personnalisé (Custom Validator).
Ces validateurs ont l'avantage de pouvoir être réutilisés, il suffit de créer le fichier password_validator.rb
dans app/validators
, puis de créer une classe qui hérite de ActiveModel::EachValidator.
Notre validateur expose une unique méthode validate_each
qui prendra toujours trois arguments :
record notre instance
#<User id: nil, email: "john@doe.fr", password: "Rubyscuit", created_at: nil, updated_at: nil>
attribute qui est
password
value, la valeur de l'input :
"Rubyscuit"
Ensuite dans notre méthode on dit que tant que le format du mot de passe ne respecte pas nos règles, on ajoute une erreur à l'attribut password
. Pour ça, on utilise record.errors.add
.
La méthode .add
prend elle aussi trois arguments :
attribute qui prendra l'attribut sur lequel on souhaite ajouter une erreur, ici
password
message est le message qui sera affiché en cas d'erreur.
options que nous n'utilisons pas ici.
Il ne nous reste plus qu'à ajouter la ligne suivante dans le modèle User
ou tout autre modèle qui aurait un attribut password
et pour lequel nous voudrions faire respecter ses règles.
C’est password: true
qui permettra à Rails de savoir magiquement qu'il doit aller chercher un validateur custom nommé PasswordValiator
.
En prime, pour simplifier le parcours de votre utilisateur, vous pouvez prévoir également une interface qui donne un retour en direct sur le champ du mot de passe pour qu'il sache s’il est valide avant de soumettre le formulaire. La CNIL fourni un exemple d'implémentation en Javascript.
Ces notions sont importantes mais ce qu'il l'est encore plus, c'est que la plateforme que vous utilisez stocke ses mots de passe de manière sécurisée. Par chance, si vous utilisez une librairie comme Devise pour l'authentification, vous n'aurez rien à faire. Voyons comment cela fonctionne.
Bonus : Comment Devise stocke les mots de passe
Avec Devise, les mots de passe de nos utilisateurs sont stockés sous le champ encrypted_password
. Si dans votre console Rails vous cherchez à en afficher un, vous ne verrez jamais le mot de passe en clair mais plutôt quelque chose qui ressemble à du charabia.
Ce charabia est en réalité le résultat du hachage du mot de passe de l'utilisateur, c'est ce qui est enregistré en base de données.
Il serait bien trop dangereux de l'enregistrer en clair, de plus nous n'aurons jamais besoin de le connaître. Lorsque notre utilisateur se connecte, le mot de passe qu'il renseigne est haché puis comparé à la valeur stockée en base de donnée, ce qui permet une connexion sécurisée sans avoir connaissance de son code secret.
Devise utilise la gem bcrypt que vous pouvez retrouver dans votre gemfile.lock
. Cette gem utilise une fonction de hachage dite à "sens unique" pour transformer les mots de passe en une chaîne de caractères de taille limitée.
Cette fonction de hachage présente plusieurs avantages :
Elle est déterministique, c'est-à-dire que le même message donne toujours lieu au même hachage
Elle permet de calculer rapidement la valeur de hachage
Il est impossible de générer un message qui donne une valeur de hachage donnée
Il est impossible de trouver deux messages différents ayant la même valeur de hachage
C'est pour cela que cette fonction est aujourd'hui une des plus sûres pour stocker des informations sensibles comme les mots de passe.
Il est important de noter que le hachage n'est pas la même chose que le chiffrement (cryptage) de données.
Comme l'explique en détail ce super article :
Avec le cryptage, si quelqu'un obtient une clé, il peut décrypter le contenu crypté. Avec le hachage, la valeur issue d'une fonction de hachage ne peut pas être inversée pour révéler le texte en clair, c'est comme convertir une vache en steak.
Vous avez maintenant toutes les cartes en mains, à vous de choisir votre politique, n'oubliez pas de respecter les recommandations de la CNIL !
Pour conclure voici une interview "d'experts de la cybersécurité", attention c'est hilarant 😂
Nouveau : Le défi
Pour la première fois je vous propose un défi !
Voici un petit kata à résoudre en moins de 15 minutes, envoyez-moi vos réponses en répondant à cette newsletter et je publierai la meilleure dans la prochaine édition !
Consigne : Ecris un algorithme qui affiche les nombres de 1 à 100 mais pour les multiples de 3 affiches “BIN”, pour les multiples de 5 affiches “GO” et pour les multiples de 3 et de 5 à la fois, affiche “BINGO”
Pour découvrir des nouveaux tips Ruby on Rails, ne cherche plus, tu es au bon endroit
Ismaël & Mélanie 🙂
Le fameux test fizzbuzz ;)
Est ce que la solution, ce n'est finalement pas, de ne pas avoir a stocker de mdp ?
Est ce que les solutions de type magik-link ne seraient pas l'avenir de la connexion a un compte ?