Properly Salting Pass­words, The Case Against Pepper


Bon, tout le monde devrait le savoir, même si mon expé­rience récente me montre qu’un rappel n’est pas inutile :

  • On ne stocke pas les mots de passe en clair, on les crypte
  • On n’uti­lise pas un chif­fre­ment réver­sible mais une fonc­tion de hachage
  • Un simple hachage ne suffit pas, il faut y ajou­ter un salage
  • Le salage doit être diffé­rent pour chaque mot de passe
  • L’al­go­rithme utilisé doit être lent, comme blow­fish par exemple

Croyez moi, j’ai encore décou­vert il y a peu que non seule­ment ce n’était pas évident pour tout le monde mais que certains refusent de consi­dé­rer un simple stockage sous forme md5 sans salage comme une erreur et un problème poten­tiel de sécu­rité.

Mais plus que tout ça, pour moi la règle de base c’est « ne jouez pas avec la sécu­rité ». Si vous n’êtes pas un expert dans la ques­tion : ne créez rien et n’im­plé­men­tez rien vous-même, utili­sez des biblio­thèques de codes toutes faites.

Et par pitié, ne tentez pas d’amé­lio­rer les choses

En jouant sur l’in­tui­tion, vous avez toutes les chances d’ar­ri­ver à un résul­tat opposé à celui que vous espé­rez.

Dans le texte du jour à lire, Properly Salting Pass­words, The Case Against Pepper, nous avons un superbe exemple que je tente d’ex­pliquer en vain à chaque fois qu’on lève le sujet :

Pour « amélio­rer » la sécu­rité, en plus du salage géré par l’al­go­rithme, propre à chaque mot de passe, certains cherchent à ajou­ter un second salage, global à l’ap­pli­ca­tion. L’idée est que le salage présent à côté du mot de passe dans la base de données ne suffit pas, il faudrait en plus connaitre le salage global utilisé par l’ap­pli­ca­tif, et donc profi­ter d’une faille de sécu­rité plus impor­tante afin d’ex­ploi­ter quoi que ce soit.

L’idée semble bonne, intui­ti­ve­ment. Malheu­reu­se­ment vous n’êtes proba­ble­ment pas un expert sur l’al­go­rithme blow­fish. Vous ne *savez* pas si ajou­ter le même salage en début ou en fin du mot de passe avant de l’en­voyer à blow­fish ne risque pas de réduire la sécu­rité du résul­tat. Oh, vous avez proba­ble­ment l’in­tui­tion que ce n’est pas le cas, voire vous en êtes certains, mais aucune docu­men­ta­tion de sécu­rité recon­nue comme étant d’au­to­rité ne le précise expli­ci­te­ment.

Vous en êtes à l’in­tui­tion et vous avez une chance sur deux de vous plan­ter. Au final, est-ce vrai­ment un bon pari ? Ça pour­rait l’être si l’état de l’art du stockage des mots de passe était fran­che­ment insuf­fi­sant et s’il n’y avait aucune méthode stan­dard pour l’amé­lio­rer. Ici il est probable que vous ne soyez pas encore à l’état de l’art (n’uti­li­se­riez-vous pas sha1 ou md5 ?) et cet état de l’art est proba­ble­ment suffi­sant si vous utili­sez suffi­sam­ment d’ité­ra­tions.

Mais plus que cette ques­tion du double salage, qui est une mauvaise idée pour ce que vous et moi en savons, c’est toute l’im­plé­men­ta­tion que vous ne devriez pas toucher. Utili­sez une biblio­thèque de code éprou­vée, ou mieux : une fonc­tion prévue pour. En PHP nous avons « crypt », qui avec avec l’al­go­rithme blow­fish et suffi­sam­ment d’ité­ra­tions, rendra votre stockage des mots de passe bien plus solide que tout le reste de votre appli­ca­tion.


7 réponses à “Properly Salting Pass­words, The Case Against Pepper”

  1. Je le mets en commentaire afin d’en diminuer l’impact : Oui, il est extrêmement probable que ce double salage aurait amélioré la sécurité (ou du moins ne l’aurait pas diminué), et encore plus probable si l’insertion du sel est faite avec un XOR ou procédé similaire et non une concaténation en début ou fin de mot de passe.

    Tout le fond de du billet et de l’article lié est dans ce terme. « Probable », même quand on y accole « extrêmement », c’est peu rassurant en sécurité.

  2. Petit détail sur l’implémentation de base de PHP, via crypt(): elle demande de générer son propre salt soi-même. Ça pose des problèmes de sécu sympa, vu que personne ne sait générer un salt correctement :-)

    Il existe 2/3 librairies qui le font bien, mais sinon, grosso modo, il faut utiliser openssl_random_pseudo_bytes() qui est fait pour ça.

    • Bof, le salt l’important est qu’il soit raisonnablement distribué dans la base et que le salt ne dépende pas trop directement du mot de passe en clair.

      Une génération aléatoire très moyenne suffit à priori puisque l’unique objectif est de casser les rainbow table (ou alors il me manque un type d’attaque).

      Maintenant oui, si crypt() est déjà un niveau au dessus des fonctions de base, utiliser une lib plus haut niveau ce n’est pas mal.

    • Le salt (par password) ne sert pas juste contres les attaques de type Rainbow Table: il sert aussi à empêcher un attaquant qui a déchiffré une entrée de ta base de déchiffrer les passwords identiques à celui la.

      Tu peux imaginer des attaques rigolotes ou un attaquant qui aurait accès à ta base, conscient de la faiblesse de ton algo de génération de salt, arrive à te forcer à utiliser le salt qu’il veut (par exemple, si ton random dépend juste du temps) et donc arrive à te faire pré-générer des hash en utilisant *ta* puissance CPU.

      En fait, en partant de cette hypothèse que le salt n’a besoin que d’être moyennement aléatoire, tu es en train de tomber dans le même travers que tu dénonces (désolé pour la formule choc): intuitivement, ça n’a pas l’air grave, mais en fait, ça l’est :)

      Les « bonnes » lib gérant ce genre de problématiques ne laissent pas le développeur gérer le salt lui-même.

    • Sauf erreur de ma part c’est juste un raccourci pour utiliser crypt() avec l’algo (dérivé de) blowfish

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.