web-dev-qa-db-fra.com

Le fait de mettre du sel en premier permet-il plus facilement à l'attaquant de forcer le hachage?

De nombreuses recommandations pour le stockage des mots de passe recommandent hash(salt + password) plutôt que hash(password + salt).

Le fait de mettre le sel en premier ne permet pas à l'attaquant de forcer le mot de passe en force, car il peut précalculer l'état de la fonction de hachage avec les octets du sel, puis à chaque fois des milliards et des milliards de tentatives, il n'a besoin que de terminer le calcul du hachage en utilisant les octets du mot de passe.

En d'autres termes, chaque itération bruteforce doit calculer uniquement le hachage du mot de passe intermediateHashState(password) au lieu de l'ensemble hash(salt + password).

Et si le sel était placé après le mot de passe, l'attaquant n'aurait pas ce raccourci.

Cet avantage existe-t-il et est-il significatif?

27
user123540

Les fonctions de hachage recommandées pour l'utilisation d'un mot de passe n'ont pas cet avantage - je ne suis pas sûr que des fonctions de hachage non triviales le fassent, mais ne voudraient pas y faire une déclaration générale.

Au lieu de cela, les fonctions de hachage mélangent les parties de l'entrée entière à chaque étape. Par exemple, étant donné l'entrée ABCDEFGHIJKLMNOPQRSTUVWXYZ, la première étape pourrait être quelque chose comme l'appariement du premier caractère avec le dernier, et l'itération jusqu'à ce qu'aucune entrée ne soit laissée. Cela donnerait AZBYCXDWEVFUGTHSIRJQKPLOMN. Supposons que le "sel" était ABCDEF et le mot de passe était le reste, puis changez le mot de passe en PASSWORD - la sortie de cet exemple de première étape serait ADBRCODWESFSPA, ce qui ne ne vous aide pas du tout avec le hachage d'origine.

Ceci n'est qu'un exemple - de vraies fonctions de hachage fonctionnent sur des valeurs binaires et effectuent un mélange plus complexe, pour quelques différences - mais vous pouvez voir que peu importe où se trouve le sel pour que la sortie change à un stade très précoce .

Il existe même un principe ( l'effet d'avalanche ) qui suggère qu'un seul bit modifié en entrée d'une fonction de hachage devrait changer environ 50% des bits de sortie, et la plupart des fonctions de hachage, même celles qui sont maintenant considérés comme dangereux comme MD5, suivez ceci (alors que mon exemple ci-dessus ne le fait pas!).

Essentiellement, vous ne pouvez pas pré-calculer une partie d'un hachage comme vous le suggérez, sauf s'il y a d'autres failles dans le système. Si, pour une raison quelconque, vous hachiez le sel, preniez la première moitié de la sortie et le boulonniez à la seconde moitié du hachage du mot de passe pour le stockage, cela introduirait la faiblesse théorique de sorte que vous n'auriez besoin que de calculer le hachages de mots de passe.

14
Matthew

En fait, vous l'abordez dans le sens inverse.

Il est vrai que faire hash(salt + password) vous permettrait de précalculer le sel (mais voir la note ci-dessous) et de hacher uniquement chaque mot de passe candidat pour tous ces essais. Le coût serait le même que si vous n'utilisiez pas du tout de sel.

Cependant, le but du sel n'est pas de rendre plus difficile le bruteforcing d'un seul hachage, mais de garantir que les hachages pour différents utilisateurs sont différents même s'ils choisissent le même mot de passe et ainsi l'effort de craquage ne peut pas être appliqué pour plusieurs utilisateurs.

Supposons que vous ayez vidé les hachages d'une base de données Paypal là où ils utilisaient les hachages MD5. Vous souhaitez vérifier les mots de passe 'Paypal', 'Paypal', 'Paypal123' ...

  1. S'ils ont utilisé MD5 (mot de passe), vous pouvez hacher trivialement n'importe lequel d'entre eux et savoir si quelqu'un utilise un mot de passe aussi faible.

  2. S'ils ont utilisé MD5 (sel + mot de passe), vous pouvez précalculer le MD5 partiel (sel) pour tout le monde, mais vous devez toujours hacher chaque mot de passe candidat pour chaque utilisateur.

  3. S'ils ont utilisé MD5 (mot de passe + sel), vous pouvez précalculer le MD5 partiel (mot de passe) pour chaque mot de passe candidat, puis appliquer leur sel pour chaque utilisateur.

Le n ° 1 est clairement le pire ici. Vous pourriez discuter entre # 2 et # 3 en fonction des différentes longueurs de mots de passe et de sels, ainsi que du nombre d'utilisateurs, mais je considère que # 2 est préférable. Sur la base de la seule longueur, la longueur minimale imposée pour vos mots de passe est probablement supérieure à la taille du sel. Mais je soupçonne qu'il pourrait aussi y avoir une autre faiblesse avec la construction # 3.

Est-ce un avantage significatif?

Pas vraiment.

Tout d'abord, de nombreuses fonctions de hachage fonctionnent en blocs, et le précalcul pour des valeurs inférieures à la taille du bloc stocke simplement une copie des "octets précalculés". Dans 99% des cas, la longueur du sel et du mot de passe sera plus courte que la taille du bloc, il n'y aurait donc pas de véritable précalcul en cours. Vous auriez besoin d'utiliser des chaînes très longues pour que cela soit utile.

De plus, toute fonction de hachage de mot de passe moderne utilisera au minimum de nombreuses itérations, si elle n'utilise pas de moyens plus avancés pour rendre le renforcement brutal coûteux, et votre optimisation ne s'applique qu'à l'itération initiale.

Dans tous les cas, plutôt que de simplement concaténer sel et mot de passe, le moyen le plus sûr de les combiner serait de faire un HMAC sur eux, ce qui les mélange dans un meilleure façon.

33
Ángel

De nombreuses recommandations pour le stockage des mots de passe recommandent hash(salt + password) plutôt que hash(password + salt).

Ces recommandations sont évidemment mauvaises, car ce qu'elles devraient vous dire, c'est d'utiliser une fonction de hachage de mot de passe spécialement conçue à cet effet, comme (par ordre approximatif du plus récent et du meilleur au plus ancien et au pire):

  • Argon2 (meilleur)
  • déchiffrer
  • bcrypt (pas mal mais commence à paraître daté)
  • PBKDF2 (loin d'être idéal mais bien meilleur que le hachage de mot de passe homebrew)

Ces fonctions:

  1. Prenez le mot de passe et le sel comme arguments séparés , et prenez donc soin de votre question en interne;
  2. Offrez-vous une API de niveau supérieur qui s'occupe de la génération et de la gestion du sel en interne:
    • Une fonction "d'inscription" qui prend un mot de passe, génère un sel et génère une chaîne de vérification qui encapsule à la fois le sel et le hachage (par exemple, password_hash() en PHP );
    • Une fonction de "vérification" qui prend un mot de passe et une chaîne de vérification, et vérifie que le mot de passe correspond à ces derniers (par exemple, password_verify() en PHP ).

Si vous concaténez manuellement des mots de passe et des sels, vous vous trompez .


Cela dit, il est généralement préférable qu'une fonction de hachage de mot de passe absorbe le sel en premier et le mot de passe ensuite. Pourquoi? Parce que cet ordre résiste mieux aux attaques de précalcul. Dans l'ordre du mot de passe en premier, l'attaquant peut précalculer les états intermédiaires qui correspondent aux mots de passe courants, et il existe peut-être un moyen intelligent de créer une sorte de grande table qui exploite cela pour calculer leurs hachages salés plus rapidement qu'ils ne le pourraient autrement. Alors que l'ordre du sel en premier rend cela impossible, d'autant plus si les sels sont aléatoires.

Le fait de mettre le sel en premier ne permet pas à l'attaquant de forcer le mot de passe en force, car il peut précalculer l'état de la fonction de hachage avec les octets du sel, puis à chaque fois des milliards et des milliards de tentatives, il n'a besoin que de terminer le calcul du hachage en utilisant les octets du mot de passe.

Non, car le fait est que l'attaquant n'est pas censé apprendre les sels avant de voler la base de mots de passe. Ce peu de précalcul que vous mentionnez ne donne qu'une petite accélération par rapport au coût d'une fonction de hachage de mot de passe bien conçue, et l'état précalculé n'est bon que pour attaquer une entrée de mot de passe individuelle (en supposant qu'il n'y ait pas de doublons, ce qui est de toute façon une exigence).

En revanche, avec l'ordre de mot de passe en premier, ils peuvent:

  • Précalculer et stocker les états de la fonction de hachage pour un grand nombre de mots de passe courants avant même qu'ils ne volent la base de données de mots de passe;
  • Réutilisez les tables précalculées dans les entrées de mot de passe hachées avec différents sels, même dans plusieurs bases de données de mots de passe.
25
Luis Casillas

Bien que les réponses ci-dessus soulèvent certains points valables, elles ne semblent pas être entièrement correctes et il convient de noter qu'il existe en fait des faiblesses dans certaines fonctions de hachage qui font une différence significative dans les vitesses de craquage pour "$ pass. $ Salt" ou "$ sel. $ pass".

Voir par exemple md5. Selon atom ( https://hashcat.net/forum/thread-8365.html ), créateur du logiciel de craquage de mot de passe hashcat:

La façon dont hashcat exploite une faiblesse de MD5 pour obtenir une accélération supplémentaire nécessite qu'il ne modifie que les 4 premiers octets des données d'entrée. Puisque cette partie est fixe (à cause du sel) elle ne peut pas utiliser l'accélération.

Cela se reflète de manière significative dans la vitesse de fissuration.
.

Des différences similaires existent pour d'autres algorithmes de hachage. Les développeurs et la communauté des logiciels de piratage de mots de passe passent beaucoup de temps à trouver des faiblesses et des raccourcis pour améliorer la vitesse. Donc, du point de vue des fissures, il peut être judicieux d'examiner les références actuelles de hashcat comme celle-ci https://Gist.github.com/Chick3nman/5d261c5798cf4f3867fe7035ef6dd49f et comparer les vitesses pour les différents Salt-Password -Variants.
Si ce lien est manquant, vous pouvez également générer votre propre benchmark avec la commande suivante:

hashcat -b
1
Denis