168 votes

Meilleures pratiques : Salage et poivrage des mots de passe ?

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]

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

  • A sel est une valeur générée de façon aléatoire, généralement stockée avec la chaîne de caractères dans la base de données, conçue pour rendre impossible l'utilisation de tables de hachage pour craquer les mots de passe. Comme chaque mot de passe a son propre sel, ils doivent tous être forcés individuellement afin de les craquer ; cependant, comme le sel est stocké dans la base de données avec le hachage du mot de passe, une compromission de la base de données signifie la perte des deux.

  • A poivre est une valeur statique 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) et destinée à rester secrète. Elle est utilisée pour qu'une compromission de la base de données ne rende pas la table de mots de passe de l'application entière forçable par brute.

Y a-t-il quelque chose qui m'échappe et le salage et le poivrage de mes mots de passe sont-ils la meilleure option pour protéger la sécurité de mes utilisateurs ? Cette méthode présente-t-elle un défaut de sécurité potentiel ?

Note : Supposons, pour les besoins de la discussion, que l'application et la base de données sont stockées sur des machines distinctes, qu'elles ne partagent pas de 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'application.

3 votes

Non bastante un duplicata, mais extrêmement liés : stackoverflow.com/questions/16594613/

2 votes

Duplicata de site croisé : security.stackexchange.com/q/3272/2113

338voto

ircmaxell Points 74865

Ok. Vu que j'ai besoin d'écrire sur ce sujet sur y sur je vais faire une dernière réponse canonique sur le poivre seul.

Les avantages apparents des poivrons

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

C'est pourquoi tant de gens pensent que les poivrons sont une bonne idée. C'est "logique".

La réalité des poivrons

Dans le domaine de la sécurité et de la cryptographie, il ne suffit pas de "donner du sens". Il faut pouvoir prouver quelque chose et avoir un sens pour qu'il soit considéré comme sûr. En outre, il doit pouvoir être mis en œuvre de manière à pouvoir être maintenu. Le système le plus sûr qui ne peut pas être maintenu est considéré comme non sécurisé (car si une partie de cette sécurité tombe en panne, le système entier s'effondre).

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

Problèmes théoriques avec les poivrons

Maintenant que nous avons planté le décor, voyons ce qui ne va pas avec les poivrons.

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

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

    L'expérience nous a appris que le fait de "nourrir" 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 la cible d'une attaque.

    C'est pourquoi des algorithmes comme PBKDF2 utiliser 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 à lancer comme ça. Les systèmes cryptographiques sont conçus pour éviter les cas "qui devraient fonctionner" et se concentrer sur les cas "conçus pour fonctionner".

    Si cela peut sembler purement théorique, ce n'est en fait pas le cas. Par exemple, Bcrypt ne peut pas accepter des mots de passe arbitraires . Donc, passer bcrypt(hash(pw), salt) peut en effet donner lieu à un hachage bien plus faible que celui de bcrypt(pw, salt) si hash() renvoie une chaîne binaire.

  • Travailler contre le design

    La façon dont bcrypt (et les autres algorithmes de hachage de mots de passe) a été conçu est de travailler avec un sel. Le concept de poivre n'a jamais été introduit. Cela peut sembler être une banalité, 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. En revanche, un poivre est, par définition, un secret cryptographique.

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

    Cela ne veut pas dire qu'il n'est pas sûr. Cela signifie que nous ne savons pas s'il est sûr. Et la recommandation générale en matière de sécurité et de cryptographie est que si nous ne le savons pas, il ne l'est pas.

    Ainsi, jusqu'à ce que des algorithmes soient conçus et approuvés par des cryptographes pour être utilisés avec des valeurs secrètes (poivres), les algorithmes actuels ne devraient pas être utilisés avec ces valeurs.

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

    Croyez-le ou non, La complexité est l'ennemi de la sécurité . Faire un algorithme qui semble complexe peut être sûr, ou ne pas l'être. Mais il y a de fortes chances qu'il ne soit pas sûr.

Problèmes importants avec les poivrons

  • Il n'est pas facile à entretenir

    Votre implémentation des poivres exclut la possibilité de faire pivoter la touche des poivres. Puisque le poivron est utilisé à l'entrée de la fonction à sens unique, vous ne pouvez jamais changer le poivron pendant toute la durée de vie de la valeur. Cela signifie que vous devez trouver des astuces bizarres pour que la rotation des touches soit prise en charge.

    C'est extrêmement importante, car elle est requise chaque fois que vous stockez des secrets cryptographiques. L'absence d'un mécanisme de rotation des clés (périodiquement et après une violation) constitue une énorme faille de sécurité.

    Et votre approche actuelle du poivre nécessiterait que chaque utilisateur ait son mot de passe complètement invalidé par une rotation, ou qu'il attende sa prochaine connexion pour effectuer une rotation (qui pourrait ne jamais avoir lieu)...

    Ce qui fait de votre approche un échec immédiat.

  • Cela vous oblige à créer votre propre crypto.

    Étant donné qu'aucun algorithme actuel ne prend en charge le concept de poivron, il vous faut soit composer des algorithmes, soit en inventer de nouveaux pour prendre en charge un poivron. Et si vous ne voyez pas immédiatement pourquoi c'est une très mauvaise chose :

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

    JAMAIS Roulez votre propre crypto...

La meilleure façon de faire

Ainsi, parmi tous les problèmes détaillés ci-dessus, il existe deux façons 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, sauf les plus faibles du dictionnaire, devraient être statistiquement sûrs. Le record actuel pour le hachage de bcrypt au coût 5 est de 71k hachages par seconde. À ce rythme, même un mot de passe aléatoire à 6 caractères prendrait des années à être craqué. Et considérant 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 de 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 catégories de mots de passe faibles à la porte et ne pas les laisser entrer. Les exigences en matière de qualité des mots de passe doivent évoluer au fur et à mesure que le piratage des mots de passe se perfectionne. C'est toujours un jeu de statistiques, mais avec une technique de stockage appropriée et des mots de passe forts, tout le monde devrait être pratiquement en sécurité...

  • Cryptage du 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. Il s'agit d'un chiffrement par blocs. Il est bon, parce qu'il est réversible, donc nous pouvons faire tourner les clés (yay ! maintenabilité !). C'est bon parce que c'est utilisé comme prévu. C'est bon parce qu'il 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 puisqu'il connaît le sel et la sortie, il peut forcer le poivre. Ok, c'est un peu long, mais c'est possible. Avec un chiffrement, l'attaquant n'obtient rien. Et puisque le sel est aléatoire, un mot de passe sentinelle ne l'aidera même pas. Donc le mieux qu'il leur reste à faire est d'attaquer la forme chiffré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 un lot de recherche sur l'attaque des chiffres, donc nous voulons nous appuyer sur cela.

TL/DR

N'utilisez pas de poivrons. Ils posent de nombreux problèmes et il existe deux meilleures méthodes : ne pas utiliser de secret côté serveur (oui, c'est correct) et chiffrer le hachage de sortie à l'aide d'un chiffrement par blocs avant de le stocker.

7 votes

Merci d'avoir inclus la dernière partie du cryptage de la valeur de hachage, c'est une réponse avec laquelle je suis entièrement d'accord. Si le cryptage devient une partie de votre api mot de passe il n'y aurait aucune raison de ne pas l'utiliser, alors peut-être... (j'adorerais écrire la documentation pour cela)

2 votes

@martinstoeckli : Je ne serais pas d'accord pour ajouter l'étape de chiffrement à l'API de hachage simplifiée. La raison 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, le bcrypt brut est plus que suffisant pour tout sauf les mots de passe les plus simples...

7 votes

@ircmaxell - D'un autre côté, vous ne perdriez rien. Dans le pire des cas, lorsque la clé est connue, un attaquant doit encore craquer le hachage BCrypt (même situation que sans cryptage). 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 pas le contrôle du serveur/code. Cette situation n'est pas rare : à part l'injection SQL, des sauvegardes jetées, des serveurs abandonnés peuvent conduire à cette situation. Beaucoup d'utilisateurs de PHP travaillent sur des serveurs hébergés.

27voto

martinstoeckli Points 6953

Tout d'abord, nous devrions parler de la l'avantage exact d'un poivre :

  • pepper peut protéger les mots de passe faibles contre 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 pepper.

Un scénario typique serait une injection SQL, des sauvegardes jetées, des serveurs mis au rebut... Ces situations ne sont pas aussi rares qu'il n'y paraît, et souvent, elles ne sont pas sous votre contrôle (hébergement de serveur). Si vous utilisez...

  • 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 un mot de passe fort dans ces conditions, même si le sel est connu. Le problème, ce sont les mots de passe faibles, qui font partie d'un dictionnaire de force brute ou qui 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 comment appliquer le poivre ?

Une façon souvent recommandée 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);

Mais il existe 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 la $serverSideKey, si cela s'avère nécessaire. Cette méthode implique un peu plus de travail, mais si le code existe déjà (bibliothèque), il n'y a aucune raison de ne pas l'utiliser.

0 votes

Donc vous diriez qu'un poivre ajoute de la sécurité par rapport à un simple sel, en résumé ? Merci pour l'aide sur la façon de mettre en œuvre.

1 votes

@LightningDust - Oui, pour les mots de passe faibles, tant que le poivre reste secret. Il atténue certains types de menaces bien définis.

0 votes

@martinstoeckli définitivement une bonne façon d'implémenter ceci. Il est bon de voir que quelqu'un ayant une certaine expérience de la sécurité soutient cette méthode. Est-ce qu'un serveur MySQL AES_ENCRYPT($passwordHash, $serverSideKey) call serait également un moyen approprié de mettre en œuvre cette mesure ?

3voto

Aron Points 5989

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

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

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

L'intérêt du sel est cependant de rendre la table arc-en-ciel de chaque utilisateur unique, ce qui augmente encore la complexité de l'attaque.

En réalité, l'objectif de la sécurité informatique n'est presque jamais de rendre la chose (mathématiquement) impossible, mais seulement 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 encore) pour calculer le mot de passe d'un seul utilisateur).

0 votes

Un sel+poivre offre-t-il plus de sécurité qu'un simple sel ? Ou serait-il préférable de laisser tomber le poivre et d'exécuter plusieurs itérations de Scrypt ?

2 votes

La principale caractéristique 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 rainbow tables disponibles pour les algorithmes de hachage les plus populaires, il suffit de se rendre sur Google !

1 votes

@LightningDust Je ne peux pas penser à une raison moi-même. Cependant, Richard, dans l'autre fil de discussion, en a trouvé une. Vous pouvez cacher le poivre dans votre code source, ce qui signifie un autre endroit auquel votre attaquant doit avoir accès, juste pour obtenir une table arc-en-ciel ensemble.

3voto

benrg Points 213

Je veux que ce soit une discussion sur les sels et les poivres et non sur des algorithmes spécifiques, mais j'en utilise un qui est sûr.

Toutes les fonctions de hachage de mot de passe sécurisées que je connais prennent le mot de passe et le sel (et le secret/le poivre s'il est supporté) comme arguments séparés et font tout le travail elles-mêmes.

Le simple fait que vous concaténiez des chaînes de caractères et que votre hash_function En ne prenant qu'un seul argument, je sais que vous n'utilisez pas l'un de ces algorithmes standard bien testés et bien analysés, mais que vous essayez plutôt de créer le vôtre. Ne faites pas ça.

Argon2 a remporté le concours de hachage de mots de passe en 2015, et pour autant que je sache, c'est toujours le meilleur choix pour les nouvelles conceptions. Il prend en charge le poivre via le paramètre K (appelé "valeur secrète" ou "clé"). Je ne connais aucune raison de ne pas utiliser pepper. Au pire, le poivre sera compromis en même temps que la base de données et vous ne serez pas plus mal loti que si vous ne l'aviez pas utilisé.

Si vous ne pouvez pas utiliser le support de poivrons intégré, vous pouvez utiliser l'une des deux formules suggérées à partir de cette discussion :

Argon2(salt, HMAC(pepper, password))   or   HMAC(pepper, Argon2(salt, password))

Note importante : si vous passez la sortie de HMAC (ou toute autre fonction de hachage) à Argon2 (ou toute autre fonction de hachage de mot de passe), assurez-vous que la fonction de hachage de mot de passe supporte les octets zéro incorporés ou bien encodez la valeur de hachage (par exemple en base64) pour vous assurer qu'il n'y a pas d'octets zéro. Si vous utilisez un langage dont les chaînes de caractères prennent en charge les octets zéro intégrés, vous êtes probablement en sécurité, sauf si ce langage est le PHP mais je vérifierais quand même.

1voto

Sven Points 879

Je ne vois pas comment le stockage d'une valeur codée en dur dans votre code source peut avoir un quelconque impact sur la sécurité. C'est la sécurité par l'obscurité.

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

1 votes

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 devrait créer une nouvelle table arc-en-ciel.

3 votes

Il renforce le hachage en se basant sur des données non disponibles dans la base de données, ce qui est une bonne chose. Les éléments de la base de données peuvent être potentiellement révélés dans les vulnérabilités - il est moins probable qu'une valeur dans le code soit accessible de la même manière.

0 votes

Les sels sont des fonctions à sens unique. Même si vous réussissez à forcer un mot de passe, vous n'obtiendrez que ce mot de passe et vous ne pourrez pas obtenir la valeur du poivre elle-même.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X