web-dev-qa-db-fra.com

Pourquoi les sels rendent-ils les attaques par dictionnaire «impossibles»?

Mise à jour: veuillez noter que je ne demande pas ce qu'est un sel, ce qu'est une table Rainbow, ce qu'est une attaque par dictionnaire ou quel est le but d'un sel. Je demande: Si vous connaissez les utilisateurs salt et hash, n'est-il pas assez facile de calculer leur mot de passe?

Je comprends le processus et le mets en œuvre moi-même dans certains de mes projets.

s =  random salt
storedPassword = sha1(password + s)

Dans la base de données que vous stockez:

username | hashed_password | salt

Chaque implémentation de salage que j'ai vue ajoute le sel à la fin du mot de passe ou au début:

hashed_Password = sha1(s + password )
hashed_Password = sha1(password + s)

Par conséquent, une attaque de dictionnaire d'un pirate qui vaut son sel (ha ha) exécuterait simplement chaque mot-clé contre les sels stockés dans les combinaisons courantes répertoriées ci-dessus.

La mise en œuvre décrite ci-dessus ajoute-t-elle simplement une autre étape pour le pirate, sans réellement résoudre le problème sous-jacent? Quelles alternatives existe-t-il pour contourner ce problème, ou ai-je mal compris le problème?

La seule chose que je puisse penser est d'avoir un algorithme de mélange secret qui associe le sel et le mot de passe dans un modèle aléatoire, ou ajoute d'autres champs utilisateur au processus de hachage, ce qui signifie que le pirate devrait avoir accès à la base de données ET au code à lacer eux pour une attaque de dictionnaire pour se révéler fructueuse. (Mise à jour, comme indiqué dans les commentaires, il est préférable de supposer que le pirate a accès à toutes vos informations, ce qui n'est probablement pas le meilleur).

Permettez-moi de donner un exemple de la façon dont je propose qu'un pirate pirate une base de données d'utilisateurs avec une liste de mots de passe et de hachages:

Données de notre base de données piratée:

RawPassword (not stored)  |  Hashed   |     Salt
--------------------------------------------------------
letmein                       WEFLS...       WEFOJFOFO...

Dictionnaire de mot de passe commun:

   Common Password
   --------------
   letmein
   12345
   ...

Pour chaque enregistrement utilisateur, bouclez les mots de passe courants et hachez-les:

for each user in hacked_DB

    salt = users_salt
    hashed_pw = users_hashed_password

    for each common_password

        testhash = sha1(common_password + salt)
        if testhash = hashed_pw then
           //Match!  Users password = common_password
           //Lets visit the webpage and login now.
        end if

    next

next

J'espère que cela illustre bien mieux mon propos.

Compte tenu de 10 000 mots de passe courants et de 10 000 enregistrements d'utilisateurs, nous aurions besoin de calculer 100 000 000 de hachages pour découvrir autant de mots de passe d'utilisateurs que possible. Cela peut prendre quelques heures, mais ce n'est pas vraiment un problème.

Mise à jour sur la théorie du cracking

Nous supposerons que nous sommes un hébergeur corrompu, qui a accès à une base de données de hachages et de sels SHA1, ainsi qu'à votre algorithme pour les mélanger. La base de données contient 10 000 enregistrements d'utilisateurs.

Ce site prétend pouvoir calculer 2 300 000 000 de hachages SHA1 par seconde en utilisant le GPU. (Dans le monde réel, la situation sera probablement plus lente, mais pour l'instant, nous utiliserons ce chiffre cité).

(((95 ^ 4)/2300000000)/2) * 10000 = 177 secondes

Étant donné une plage complète de 95 caractères ASCII imprimables, d'une longueur maximale de 4 caractères, divisés par le taux de calcul (variable), divisés par 2 (en supposant que le temps moyen pour découvrir le mot de passe sera activé) nécessitent en moyenne 50% de permutations) pour 10 000 utilisateurs, il faudrait 177 secondes pour définir tous les mots de passe des utilisateurs dont la longueur est <= 4.

Ajustez-le un peu pour le réalisme.

(((36 ^ 7)/1000000000)/2) * 10000 = 2 jours

En supposant une sensibilité à la casse, avec une longueur de mot de passe <= 7, uniquement des caractères alphanumériques, il faudrait 4 jours pour résoudre 10 000 enregistrements utilisateur, et j'ai réduit de moitié la vitesse de l'algorithme pour refléter les frais généraux et les circonstances non idéales.

Il est important de reconnaître qu'il s'agit d'une attaque par force brute linéaire, tous les calculs sont indépendants les uns des autres, c'est donc une tâche parfaite à résoudre pour plusieurs systèmes. (IE facile à configurer 2 ordinateurs exécutant une attaque à des fins différentes qui réduirait la moitié du temps d'exécution).

Étant donné le cas du hachage récursif d'un mot de passe 1000 fois pour rendre cette tâche plus coûteuse en termes de calcul:

(((36 ^ 7)/1 000 000 000)/2) * 1000 secondes = 10,8839117 heures

Cela représente une longueur maximale de 7 caractères alphanumériques, à une exécution inférieure à la moitié de la vitesse de la figure citée pour un utilisateur.

Le hachage récursif 1 000 fois bloque efficacement une attaque globale, mais les attaques ciblées sur les données des utilisateurs sont toujours vulnérables.

85
Tom Gullen

Oui, vous n'avez besoin que de 3 jours pour sha1 (sel | mot de passe). C'est pourquoi de bons algorithmes de stockage de mots de passe utilisent un hachage de 1000 itérations: vous aurez besoin de 8 ans.

30
blaze

Cela n'arrête pas les attaques par dictionnaire.

Ce qu'il fait, c'est d'empêcher quelqu'un qui parvient à obtenir une copie de votre fichier de mot de passe d'utiliser un Rainbow table pour comprendre quels sont les mots de passe des hachages.

Finalement, cela peut être forcé par la force brute, cependant. La réponse à cette partie est de forcer vos utilisateurs à ne pas utiliser les mots du dictionnaire comme mots de passe (exigences minimales d'au moins un chiffre ou caractère spécial, par exemple).

Mise à jour :

J'aurais dû le mentionner plus tôt, mais certains systèmes de mots de passe (la plupart?) Utilisent un sel différent pour chaque mot de passe, probablement stocké avec le mot de passe lui-même. Cela rend une seule table Rainbow inutile. C'est ainsi que fonctionne la bibliothèque UNIX crypt , et les systèmes d'exploitation modernes de type UNIX ont étendu cette bibliothèque avec de nouveaux algorithmes de hachage.

Je sais pertinemment que la prise en charge de SHA-256 et SHA-512 a été ajoutée dans les nouvelles versions de GNU crypt.

62
Powerlord

Pour être plus précis, une attaque par dictionnaire , c'est-à-dire une attaque où tous les mots d'une liste exhaustive sont essayés, n'est pas "impossible", mais elle devient impraticable : chaque bit de sel double la quantité de stockage et de calcul requise .

Ceci est différent des attaques par dictionnaire pré-calculées comme les attaques impliquant des tables Rainbow où il n'a pas d'importance si le sel est secret ou non.

Exemple: avec un sel 64 bits (soit 8 octets), vous devez vérifier 264 combinaisons de mots de passe supplémentaires dans votre attaque par dictionnaire. Avec un dictionnaire contenant 200 000 mots vous devrez faire

200 000 * 264 = 3,69 * 1024

tests dans le pire des cas - au lieu de 200 000 tests sans sel.

Un avantage supplémentaire de l'utilisation de salt est qu'un attaquant ne peut pas pré-calculer les hachages de mot de passe à partir de son dictionnaire. Cela prendrait simplement trop de temps et/ou d'espace.

Mise à jour

Votre mise à jour suppose qu'un attaquant connaît déjà le sel (ou l'a volé). C'est bien sûr une situation différente. Il n'est toujours pas possible pour l'attaquant d'utiliser une table Rainbow pré-calculée. Ce qui importe ici, c'est la vitesse de la fonction de hachage. Pour rendre une attaque impossible, la fonction de hachage doit être lente. MD5 ou SHA ne sont pas de bons candidats ici car ils sont conçus pour être rapides, les meilleurs candidats pour les algorithmes de hachage sont Blowfish ou certaines variantes de celui-ci.

Mise à jour 2

Une bonne lecture sur la question de la sécurisation de vos hachages de mot de passe en général (allant bien au-delà de la question d'origine mais toujours intéressante):

Assez avec les tableaux arc-en-ciel: ce que vous devez savoir sur les schémas de mots de passe sécurisés

Corollaire de l'article: utilisez des hachages salés créés avec bcrypt (basé sur Blowfish) ou Eksblowfish qui vous permet d'utiliser un temps de configuration configurable pour ralentir le hachage.

30
Dirk Vollmar

Un dictionnaire est une structure où les valeurs sont indexées par des clés. Dans le cas d'une attaque par dictionnaire pré-calculée, chaque clé est un hachage et la valeur correspondante est un mot de passe qui entraîne le hachage. Avec un dictionnaire pré-calculé en main, un attaquant peut rechercher "instantanément" un mot de passe qui produira le hachage nécessaire pour se connecter.

Avec le sel, l'espace requis pour stocker le dictionnaire augmente rapidement… si rapidement, qu'essayer de pré-calculer un dictionnaire de mots de passe devient vite inutile.

Les meilleurs sels sont choisis au hasard dans un générateur de nombres aléatoires cryptographiques. Huit octets ont une taille pratique et plus de 16 octets ne servent à rien.


Le sel fait bien plus que "rendre le travail d'un attaquant plus irritant". Il élimine toute une classe d'attaques: l'utilisation de dictionnaires précalculés.

Un autre élément est nécessaire pour sécuriser complètement les mots de passe, c'est le "renforcement des clés". Un tour de SHA-1 n'est pas suffisant: un algorithme de hachage de mot de passe sûr devrait être très lent sur le plan informatique.

De nombreuses personnes utilisent PBKDF2, une fonction de dérivation de clé, qui renvoie les résultats à la fonction de hachage des milliers de fois. L'algorithme "bcrypt" est similaire, utilisant une dérivation de clé itérative lente.

Lorsque l'opération de hachage est très lente, une table précalculée devient de plus en plus souhaitable pour un attaquant. Mais le sel approprié défait cette approche.


Commentaires

Voici les commentaires que j'ai faits sur la question.


Sans sel, un attaquant n'utiliserait pas la méthode illustrée dans "Update 2". Il ferait simplement une recherche dans une table pré-calculée et obtiendrait le mot de passe en O(1) ou O (log n) temps (n étant le nombre de mots de passe candidats). Le sel est ce qui l'empêche et l'oblige à utiliser l'approche O(n) montrée dans "Update 2".

Une fois réduit à une attaque O(n), nous devons considérer combien de temps chaque tentative prend. Le renforcement des clés peut faire que chaque tentative dans la boucle prenne une seconde complète, ce qui signifie que le temps nécessaire pour tester des mots de passe de 10 000 sur des utilisateurs de 10 000 s'étendra de 3 jours à 3 ans … et avec seulement 10 000 mots de passe, vous risquez de casser zéro mot de passe temps.

Vous devez considérer qu'un attaquant va utiliser les outils les plus rapides qu'il peut, pas PHP, donc des milliers d'itérations, plutôt que 100, seraient un bon paramètre pour le renforcement des clés. Cela devrait prendre une grande fraction de seconde pour calculer le hachage pour un seul mot de passe.

Le renforcement des clés fait partie des algorithmes de dérivation de clés standard PBKDF1 et PBKDF2, de PKCS # 5, qui constituent d'excellents algorithmes d'obscurcissement de mot de passe (la "clé dérivée" est le "hachage").

Beaucoup d'utilisateurs sur StackOverflow se réfèrent à cet article parce que c'était une réponse au post de Jeff Atwood sur les dangers des tables Rainbow. Ce n'est pas mon article préféré, mais il aborde ces concepts plus en détail.


Bien sûr, vous supposez que l'attaquant a tout: sel, hachage, nom d'utilisateur. Supposons que l'attaquant est un employé corrompu de la société d'hébergement qui a vidé la table des utilisateurs sur votre site de fans myprettypony.com. Il essaie de récupérer ces mots de passe parce qu'il va se retourner et voir si vos fans de poney ont utilisé le même mot de passe sur leurs comptes citibank.com.

Avec un schéma de mots de passe bien conçu, il sera impossible pour ce type de récupérer les mots de passe.

17
erickson

Le but du salage est d'empêcher l'amortissement de l'effort de l'attaquant.

Sans sel, une seule table d'entrées de mot de passe de hachage précalculées (par exemple, MD5 de toutes les chaînes alphanumériques de 5 caractères, faciles à trouver en ligne) peut être utilisée pour chaque utilisateur dans chaque base de données dans le monde.

Avec un sel spécifique au site, l'attaquant doit calculer lui-même la table et peut ensuite l'utiliser sur tous les utilisateurs du site.

Avec un sel par utilisateur, l'attaquant doit consacrer cet effort à chaque utilisateur séparément.

Bien sûr, cela ne fait pas grand-chose pour protéger les mots de passe vraiment faibles directement d'un dictionnaire, mais cela protège les mots de passe raisonnablement forts contre cet amortissement.

7
Michael Borgwardt

De plus - un autre point important - l'utilisation d'un sel spécifique à USER empêche la détection de deux utilisateurs avec le même mot de passe - leurs hachages correspondraient. C'est pourquoi plusieurs fois le hachage est un hachage (sel + nom d'utilisateur + mot de passe)

Si vous essayez de garder le hachage secret, l'attaquant ne peut pas non plus vérifier les hachages.

Edit- vient de remarquer que le point principal a été fait dans un commentaire ci-dessus.

6
Dominik Weber

Des sels sont mis en œuvre pour empêcher les attaques de table arc-en-ciel. Une table Rainbow est une liste de hachages pré-calculés, ce qui rend la traduction d'un hachage en sa phrase beaucoup plus simple. Vous devez comprendre que le salage n'est pas efficace comme moyen de prévention moderne pour casser un mot de passe à moins que nous ayons un algo de hachage moderne.

Disons donc que nous travaillons avec SHA1, en tirant parti des récents exploits découverts avec cet algo, et disons que nous avons un ordinateur fonctionnant à 1 000 000 de hachages/seconde, il faudrait 5,3 millions de millions d'années pour trouver une collision , donc ouais php peut fonctionner 300 secondes, gros woop, ça n'a pas vraiment d'importance. La raison pour laquelle nous saluons est que si quelqu'un a pris la peine de générer toutes les phrases de dictionnaire courantes, (2 ^ 160 personnes, bienvenue aux exploits de l'ère 2007).

Voici donc une base de données réelle, avec 2 utilisateurs que j'utilise à des fins de test et d'administration.

RegistrationTime        UserName        UserPass    
1280185359.365591       briang      a50b63e927b3aebfc20cd783e0fc5321b0e5e8b5
1281546174.065087       test        5872548f2abfef8cb729cac14bc979462798d023

En fait, le schéma de salage est votre sha1 (heure d'enregistrement + nom d'utilisateur). Allez-y, dites-moi mon mot de passe, ce sont de vrais mots de passe en production. Vous pouvez même vous asseoir et hacher une liste de mots en php. Devenir fou.

Je ne suis pas fou, je sais juste que c'est sûr. Pour le plaisir, le mot de passe du test est test. sha1(sha1(1281546174.065087 + test) + test) = 5872548f2abfef8cb729cac14bc979462798d023

Vous devez générer une table Rainbow entière composée de 27662aee8eee1cb5ab4917b09bdba31d091ab732 Pour juste cet utilisateur. Cela signifie que je peux réellement permettre que mes mots de passe ne soient pas tous compromis par une seule table Rainbow, le pirate doit générer une table Rainbow entière pour 27662aee8eee1cb5ab4917b09bdba31d091ab732 pour le test, et encore f3f7735311217529f2e020468004a2aa5b3dee. Pensez aux 5,3 millions de millions d'années pour tous les hachages. Pensez à la taille du stockage des 2 ^ 80 hachages (c'est bien plus de 20 yottabytes ), ça ne va pas arriver.

Ne confondez pas le salage comme un moyen de faire un hachage quelque chose que vous ne pouvez jamais décoder, c'est un moyen d'empêcher une table Rainbow de traduire tout votre mots de passe utilisateur. C'est impossible à ce niveau de technologie.

5
Incognito

L'idée derrière l'attaque par dictionnaire est que vous prenez un hachage et trouvez le mot de passe, à partir duquel ce hachage a été calculé, sans calcul du hachage. Maintenant, faites de même avec un mot de passe salé - vous ne pouvez pas.

Ne pas utiliser de sel rend la recherche de mot de passe aussi simple que la recherche dans la base de données. L'ajout d'un sel fait que l'attaquant effectue un calcul de hachage de tous les mots de passe possibles (même pour le dictionnaire, cela augmente considérablement le temps d'attaque).

Le simple fait de saler n'empêche pas un hachage d'attaquer (bruteforce ou dictionnaire), il ne fait que le rendre plus difficile; l'attaquant devra soit trouver l'algorithme de salage (qui, s'il est correctement mis en œuvre, utilisera plus d'itérations), soit forcer l'algo, qui, à moins qu'il ne soit très simple, est presque impossible. Le salage rejette également presque complètement l'option des recherches de table Rainbow ...

2
cyber-guard

En termes plus simples: sans salage, chaque mot de passe candidat n'a besoin d'être haché qu'une seule fois pour le comparer à chaque utilisateur, n'importe où dans "l'univers connu" (collection de bases de données compromises), dont le mot de passe est haché via le même algorithme. Avec le salage, si le nombre de valeurs de sel possibles dépasse sensiblement le nombre d'utilisateurs dans "l'univers connu", chaque mot de passe candidat doit être haché séparément pour chaque utilisateur contre lequel il sera testé.

2
supercat

Salt rend Table arc-en-ciel les attaques beaucoup plus difficiles car cela rend le hachage d'un mot de passe unique beaucoup plus difficile à déchiffrer. Imaginez que vous ayez un horrible mot de passe uniquement le numéro 1. Une attaque de table Rainbow le casserait immédiatement.

Imaginez maintenant que chaque mot de passe dans la base de données soit salé avec une longue valeur aléatoire de nombreux caractères aléatoires. Maintenant, votre mot de passe moche de "1" est stocké dans la base de données comme un hachage de 1 plus un tas de caractères aléatoires (le sel), donc dans cet exemple, la table Rainbow doit avoir le hachage pour quelque chose comme: 1.

Donc, en supposant que votre sel est quelque chose de sécurisé et aléatoire, disons ()% ISLDGHASKLU (% #% #, la table Rainbow du pirate devrait avoir une entrée pour 1 * ()% ISLDGHASKLU (*% #% #. Maintenant, utiliser une table Rainbow sur ce simple mot de passe n'est plus pratique.

1
Cory House