Meilleures pratiques: saler et poivrer les mots de passe?

145

Je suis tombé sur une discussion dans laquelle j'ai appris que ce que je faisais n'était pas en fait de saler les mots de passe, mais de les poivrer, et j'ai depuis commencé à faire les deux avec une fonction comme:

hash_function($salt.hash_function($pepper.$password)) [multiple iterations]

En ignorant l'algorithme de hachage choisi (je veux que ce soit une discussion sur les sels et les poivrons et non sur des algorithmes spécifiques mais j'utilise un algorithme sécurisé), est-ce une option sécurisée ou devrais-je faire quelque chose de différent? Pour ceux qui ne connaissent pas les termes:

  • Un salt est une valeur générée aléatoirement généralement stockée avec la chaîne dans la base de données conçue pour rendre impossible l'utilisation de tables de hachage pour déchiffrer les mots de passe. Comme chaque mot de passe a son propre sel, ils doivent tous être forcés individuellement afin de les déchiffrer; cependant, comme le sel est stocké dans la base de données avec le hachage du mot de passe, un compromis de base de données signifie perdre les deux.

  • Un pepper est une valeur statique à l'échelle du site stockée séparément de la base de données (généralement codée en dur dans le code source de l'application) qui est censée être secrète. Il est utilisé pour qu'une compromission de la base de données n'entraîne pas la force brute de la table des mots de passe de l'application entière.

Y a-t-il quelque chose qui me manque et est-ce que saler et poivrer mes mots de passe est la meilleure option pour protéger la sécurité de mon utilisateur? Y a-t-il une faille de sécurité potentielle à faire de cette façon?

Remarque: Supposons, aux fins de la discussion, que l'application et la base de données sont stockées sur des machines distinctes, ne partagent pas les mots de passe, etc., de sorte qu'une violation du serveur de base de données ne signifie pas automatiquement une violation du serveur d'applications.

Désir de glitch
la source
3
Pas tout à fait un doublon, mais extrêmement lié: stackoverflow.com/questions/16594613/…
ircmaxell
2
Double site Web: security.stackexchange.com/q/3272/2113
Jacco

Réponses:

306

D'accord. Vu que j'ai besoin d'écrire à ce sujet encore et encore , je vais faire une dernière réponse canonique sur le poivre seul.

Le revers apparent des poivrons

Il semble assez évident que les piments devraient rendre les fonctions de hachage plus sécurisées. Je veux dire, si l'attaquant n'obtient que votre base de données, les mots de passe de vos utilisateurs doivent être sécurisés, non? Cela semble logique, non?

C'est pourquoi tant de gens pensent que les poivrons sont une bonne idée. Ca a du sens".

La réalité des poivrons

Dans les domaines de la sécurité et de la cryptographie, «faire sens» ne suffit pas. Quelque chose doit être prouvable et avoir du sens pour être considéré comme sûr. De plus, il doit être implémentable de manière maintenable. Le système le plus sécurisé qui ne peut pas être maintenu est considéré comme non sécurisé (car si une partie de cette sécurité tombe en panne, tout le système s'effondre).

Et les poivrons ne conviennent ni aux modèles prouvables ni aux modèles maintenables ...

Problèmes théoriques avec les poivrons

Maintenant que nous avons préparé le terrain, regardons ce qui ne va pas avec les poivrons.

  • Nourrir un hasch dans un autre peut être dangereux.

    Dans votre exemple, vous faites hash_function($salt . hash_function($pepper . $password)).

    Nous savons par expérience que «simplement alimenter» un résultat de hachage dans une autre fonction de hachage peut diminuer la sécurité globale. La raison en est que les deux fonctions de hachage peuvent devenir une cible d'attaque.

    C'est pourquoi des algorithmes comme PBKDF2 utilisent des opérations spéciales pour les combiner (hmac dans ce cas).

    Le fait est que même si ce n'est pas un gros problème, ce n'est pas non plus une chose triviale à jeter. Les systèmes cryptographiques sont conçus pour éviter les cas «devraient fonctionner», et se concentrent plutôt sur les cas «conçus pour fonctionner».

    Bien que cela puisse sembler purement théorique, ce n'est en fait pas le cas. Par exemple, Bcrypt ne peut pas accepter les mots de passe arbitraires . Ainsi, le passage bcrypt(hash(pw), salt)peut en effet entraîner un hachage beaucoup plus faible que bcrypt(pw, salt)si hash()renvoie une chaîne binaire.

  • Travailler contre le design

    La façon dont bcrypt (et d'autres algorithmes de hachage de mot de passe) ont été conçus est de fonctionner avec un sel. Le concept de poivre n'a jamais été introduit. Cela peut sembler trivial, mais ce n'est pas le cas. La raison en est qu'un sel n'est pas un secret. C'est juste une valeur qui peut être connue d'un attaquant. Un poivre en revanche, par définition même, est un secret cryptographique.

    Les algorithmes de hachage de mot de passe actuels (bcrypt, pbkdf2, etc.) sont tous conçus pour n'accepter qu'une seule valeur secrète (le mot de passe). L'ajout d'un autre secret dans l'algorithme n'a pas du tout été étudié.

    Cela ne veut pas dire que ce n'est pas sûr. Cela signifie que nous ne savons pas si c'est sûr. Et la recommandation générale concernant la sécurité et la cryptographie est que si nous ne le savons pas, ce n'est pas le cas.

    Ainsi, tant que les algorithmes ne sont pas conçus et approuvés par des cryptographes pour une utilisation avec des valeurs secrètes (piments), les algorithmes actuels ne doivent pas être utilisés avec eux.

  • La complexité est l'ennemi de la sécurité

    Croyez-le ou non, la complexité est l'ennemi de la sécurité . Créer un algorithme qui semble complexe peut être sûr ou non. Mais les chances sont assez importantes que ce ne soit pas sécurisé.

Problèmes importants avec les poivrons

  • Ce n'est pas maintenable

    Votre mise en œuvre de poivrons empêche la possibilité de faire pivoter la clé de poivre. Puisque le poivre est utilisé à l'entrée de la fonction unidirectionnelle, vous ne pouvez jamais changer le poivre pour la durée de vie de la valeur. Cela signifie que vous devrez trouver des hacks loufoques pour qu'il prenne en charge la rotation des clés.

    Ceci est extrêmement important car il est nécessaire chaque fois que vous stockez des secrets cryptographiques. Le fait de ne pas disposer d'un mécanisme pour faire pivoter les clés (périodiquement et après une brèche) est une énorme vulnérabilité de sécurité.

    Et votre approche actuelle de pepper exigerait que chaque utilisateur soit complètement invalidé par une rotation, soit attende sa prochaine connexion pour tourner (ce qui peut ne jamais être) ...

    Ce qui fait de votre approche une interdiction immédiate.

  • Cela vous oblige à rouler votre propre crypto

    Puisqu'aucun algorithme actuel ne prend en charge le concept de poivre, il vous oblige à composer des algorithmes ou à en inventer de nouveaux pour supporter un poivre. Et si vous ne pouvez pas voir immédiatement pourquoi c'est une très mauvaise chose:

    N'importe qui, de l'amateur le plus ignorant au meilleur cryptographe, peut créer un algorithme qu'il ne peut pas casser lui-même.

    NE JAMAIS rouler votre propre crypto ...

La meilleure façon

Ainsi, parmi tous les problèmes détaillés ci-dessus, il existe deux manières de gérer la situation.

  • Utilisez simplement les algorithmes tels qu'ils existent

    Si vous utilisez correctement bcrypt ou scrypt (avec un coût élevé), tous les mots de passe de dictionnaire sauf les plus faibles devraient être statistiquement sûrs. L'enregistrement actuel pour le hachage de bcrypt au coût 5 est de 71 000 hachages par seconde. À ce rythme, même un mot de passe aléatoire de 6 caractères prendrait des années à se déchiffrer. Et étant donné que mon coût minimum recommandé est de 10, cela réduit les hachages par seconde par un facteur de 32. Nous ne parlerions donc que d'environ 2200 hachages par seconde. À ce rythme, même certaines phrases ou modifications du dictionnaire peuvent être sûres.

    De plus, nous devrions vérifier ces faibles classes de mots de passe à la porte et ne pas les autoriser. À mesure que le craquage des mots de passe devient plus avancé, les exigences de qualité des mots de passe devraient également l'être. C'est toujours un jeu statistique, mais avec une technique de stockage appropriée et des mots de passe forts, tout le monde devrait être pratiquement en sécurité ...

  • Crypter le hachage de sortie avant le stockage

    Il existe dans le domaine de la sécurité un algorithme conçu pour gérer tout ce que nous avons dit ci-dessus. C'est un chiffrement par blocs. C'est bien, car c'est réversible, donc on peut faire tourner les clés (yay! Maintenabilité!). C'est bien parce qu'il est utilisé comme prévu. C'est bien car cela ne donne aucune information à l'utilisateur.

    Regardons à nouveau cette ligne. Disons qu'un attaquant connaît votre algorithme (ce qui est nécessaire pour la sécurité, sinon c'est la sécurité par l'obscurité). Avec une approche traditionnelle du poivre, l'attaquant peut créer un mot de passe sentinelle, et comme il connaît le sel et la sortie, il peut forcer brutalement le poivre. Ok, c'est loin, mais c'est possible. Avec un chiffre, l'attaquant n'obtient rien. Et comme le sel est randomisé, un mot de passe sentinelle ne l'aidera même pas. Le mieux qu'il leur reste est donc d'attaquer la forme cryptée. Ce qui signifie qu'ils doivent d'abord attaquer votre hachage chiffré pour récupérer la clé de chiffrement, puis attaquer les hachages. Mais il y a beaucoup de recherches sur l'attaque des chiffrements, nous voulons donc nous en remettre.

TL / DR

N'utilisez pas de poivrons. Il y a une foule de problèmes avec eux, et il y a deux meilleures façons: ne pas utiliser de secret côté serveur (oui, ça va) et crypter le hachage de sortie en utilisant un chiffrement par bloc avant le stockage.

ircmaxell
la source
6
Merci d'avoir inclus cette dernière partie du chiffrement de la valeur de hachage, c'est une réponse avec laquelle je suis entièrement d'accord. Si le cryptage faisait partie de votre API de mot de passe , il n'y aurait aucune raison de ne pas l'utiliser, alors peut-être ... (j'aimerais écrire la documentation pour cela)
martinstoeckli
2
@martinstoeckli: Je n'accepterais pas d'ajouter l'étape de chiffrement à l'API de hachage simplifiée. La raison en est que le stockage des secrets (clés) est beaucoup plus difficile que les gens ne le pensent, et il est assez facile de se tirer une balle dans le pied. Pour 99,9% des utilisateurs, bcrypt brut est plus que suffisant pour tous les mots de passe, sauf les plus simples ...
ircmaxell
7
@ircmaxell - De l'autre côté, vous ne perdriez rien. Dans le pire des cas, lorsque la clé devient connue, un attaquant doit quand même déchiffrer le hachage BCrypt (même situation que sans chiffrement). Ce n'est pas la même chose que de stocker une clé pour crypter des données, il s'agit d'ajouter un secret côté serveur. Même une clé codée en dur protégerait ces mots de passe faibles, tant que l'attaquant n'a aucun contrôle sur le serveur / code. Cette situation n'est pas rare: outre l'injection SQL, les sauvegardes jetées, les serveurs abandonnés… peuvent conduire à cette situation. De nombreux utilisateurs PHP travaillent sur des serveurs hébergés.
martinstoeckli
2
@martinstoeckli Je devrais être d'accord avec ircmaxwell ici, je ne pense pas que le cryptage appartient à l'API de mot de passe. Cependant, il peut être noté que pour une sécurité maximale, le chiffrement de vos hachages est une disposition supplémentaire qui peut être utilisée.
foochow
1
On m'a indiqué la section 2.4.5 de la norme de vérification de la sécurité des applications OWASP 4.0 , qui recommande d'utiliser le sel secret (aka pepper): «Vérifiez qu'une itération supplémentaire d'une fonction de dérivation de clé est effectuée, en utilisant une valeur de sel secrète et connue uniquement de le vérificateur. »
Michael Freidgeim
24

Fist nous devrions parler de l' avantage exact d'un poivre :

  • Le pepper peut protéger les mots de passe faibles d'une attaque par dictionnaire, dans le cas particulier, où l'attaquant a un accès en lecture à la base de données (contenant les hachages) mais n'a pas accès au code source avec le pepper.

Un scénario typique serait l'injection SQL, les sauvegardes jetées, les serveurs abandonnés ... Ces situations ne sont pas aussi rares qu'il y paraît, et souvent pas sous votre contrôle (hébergement de serveur). Si tu utilises...

  • Un sel unique par mot de passe
  • Un algorithme de hachage lent comme BCrypt

... les mots de passe forts sont bien protégés. Il est presque impossible de forcer brutalement un mot de passe fort dans ces conditions, même lorsque le sel est connu. Le problème, ce sont les mots de passe faibles, qui font partie d'un dictionnaire de force brute ou en sont des dérivés. Une attaque par dictionnaire les révélera très rapidement, car vous ne testez que les mots de passe les plus courants.

La deuxième question est de savoir comment appliquer le poivre ?

Un moyen souvent recommandé d'appliquer un poivre est de combiner le mot de passe et le poivre avant de le passer à la fonction de hachage:

$pepperedPassword = hash_hmac('sha512', $password, $pepper);
$passwordHash = bcrypt($pepperedPassword);

Il existe cependant un autre moyen encore meilleur:

$passwordHash = bcrypt($password);
$encryptedHash = encrypt($passwordHash, $serverSideKey);

Cela permet non seulement d'ajouter un secret côté serveur, mais aussi d'échanger le $ serverSideKey, si cela est nécessaire. Cette méthode implique un peu plus de travail, mais si le code existe une fois (bibliothèque), il n'y a aucune raison de ne pas l'utiliser.

martinstoeckli
la source
Donc, vous diriez qu'un poivre ajoute de la sécurité sur juste un sel, en bref? Merci pour l'aide sur la façon de mettre en œuvre.
Glitch Desire
1
@LightningDust - Oui, c'est le cas, pour les mots de passe faibles, tant que le poivre reste secret. Il atténue certains types de menaces bien définis.
martinstoeckli
@martinstoeckli est certainement un bon moyen de mettre en œuvre cela. C'est bien de voir que quelqu'un avec une certaine expérience de la sécurité prend en charge cette méthode. Un AES_ENCRYPT($passwordHash, $serverSideKey)appel MySQL serait-il également un moyen approprié d'implémenter cela?
foochow
1
@Foo_Chow - Je ne connais pas l'implémentation de la fonction MySQL, mais il semble qu'ils ont utilisé le mode EBC, pour éviter le vecteur IV. Avec le texte brut connu (les valeurs de hachage commencent toujours par les mêmes caractères), cela pourrait être un problème. Sur ma page d'accueil, j'ai publié un exemple d'implémentation, qui gère ce cryptage.
martinstoeckli
@martinstoeckli intéressant, pas trop familier avec les concepts; cependant semble qu'une IV serait souhaitable pour les résultats les plus robustes. Ne semble pas ajouter beaucoup de frais généraux pour l'avantage supplémentaire.
foochow
2

L'intérêt du sel et du poivre est d'augmenter le coût d'une recherche de mot de passe pré-calculée, appelée table arc-en-ciel.

En général, essayer de trouver une collision pour un seul hachage est difficile (en supposant que le hachage est sécurisé). Cependant, avec des hachages courts, il est possible d'utiliser un ordinateur pour générer tous les hachages possibles dans une recherche sur un disque dur. C'est ce qu'on appelle une Rainbow Table. Si vous créez une table arc-en-ciel, vous pouvez alors sortir dans le monde et trouver rapidement des mots de passe plausibles pour tout hachage (non salé).

Le but d'un poivre est de rendre la table arc-en-ciel nécessaire pour pirater votre liste de mots de passe unique. Perdant ainsi plus de temps à l'attaquant pour construire la table arc-en-ciel.

Le but du sel est cependant de rendre la table arc-en-ciel de chaque utilisateur unique pour l'utilisateur, augmentant encore la complexité de l'attaque.

En réalité, le but de la sécurité informatique n'est presque jamais de la rendre (mathématiquement) impossible, juste mathématiquement et physiquement irréalisable (par exemple, dans les systèmes sécurisés, il faudrait toute l'entropie de l'univers (et plus) pour calculer le mot de passe d'un seul utilisateur).

Aron
la source
Alors, un sel + poivre offre-t-il plus de sécurité qu'un simple sel? Ou est-ce que je ferais mieux de laisser tomber le poivre et d'exécuter plus d'itérations de scrypt?
Glitch Desire
2
La principale chose à propos d'une table arc-en-ciel est que vous n'en créez pas une pour une attaque spécifique, vous en téléchargez une préexistante. Il existe de longues tables arc-en-ciel disponibles pour les algorithmes de hachage populaires à portée de Google!
Richard
1
@LightningDust Je ne vois aucune raison moi-même. Cependant, Richard dans l'autre fil en a proposé un. Vous pouvez cacher le poivre dans votre code source, ce qui signifie un autre endroit auquel votre attaquant doit accéder, juste pour rassembler une table arc-en-ciel.
Aron
@Aron - Eh bien, c'est ce que je pensais, puisque nous avons des serveurs d'applications séparés des serveurs de base de données (c'est-à-dire que si vous vous trouvez rootsur notre serveur db, vous n'avez toujours pas accès à notre serveur d'application), qui cache du poivre dans le code source (en notre fichier de configuration) fournirait une sécurité supplémentaire.
Glitch Desire
1

Vous ne voyez pas le stockage d'une valeur codée en dur dans votre code source comme ayant une importance pour la sécurité. C'est la sécurité par l'obscurité.

Si un hacker acquiert votre base de données, il pourra commencer à forcer brutalement vos mots de passe utilisateur. Il ne faudra pas longtemps à ce hacker pour identifier votre piment s'il parvient à déchiffrer quelques mots de passe.

Sven
la source
1
Cela rendrait inutile une table arc-en-ciel précalculée pour une table de mots de passe non salée. En bref, même si l'attaquant connaissait votre poivre, il aurait besoin de créer une nouvelle table arc-en-ciel.
Aron
3
Il renforce le hachage en fonction de données non disponibles dans la base de données, ce qui est une bonne chose. Des éléments de la base de données peuvent être potentiellement révélés dans des vulnérabilités - il est moins probable qu'une valeur du code soit accessible de la même manière.
Richard
Les sels sont des fonctions à sens unique, même le fait de forcer un mot de passe avec succès ne vous donnerait que ce mot de passe et ne vous aiderait pas à obtenir la valeur du poivre lui-même.
Glitch Desire
1
@LightningDust Je pense que vous voulez dire "les hachages sont des fonctions de trappe". Oui, il est impossible de déterminer votre sel et / ou poivre à partir d'un hachage sécurisé (en fait, c'est la définition d'un hachage sécurisé).
Aron
6
@Aron Security Through Obscurity peut être une technique valide utilisée comme couche de défense. Le fait est qu'il ne devrait jamais être invoqué comme défense, mais plutôt utilisé pour "ralentir un attaquant". Si ce n'était pas le cas, quelque chose comme un pot de miel ne serait pas utilisé. Au lieu de cela, nous pouvons utiliser efficacement la sécurité par l'obscurité pour aider à ralentir les attaquants, tant que nous ne comptons pas sur elle pour la sécurité de notre application.
ircmaxell