Hachage et sel sécurisés pour les mots de passe PHP


1174

On dit actuellement que MD5 est partiellement dangereux. Compte tenu de cela, je voudrais savoir quel mécanisme utiliser pour la protection par mot de passe.

Cette question, le «double hachage» est-il un mot de passe moins sûr qu'un simple hachage une fois? suggère que le hachage plusieurs fois peut être une bonne idée, alors comment mettre en œuvre la protection par mot de passe pour des fichiers individuels? suggère d'utiliser du sel.

J'utilise PHP. Je veux un système de cryptage de mot de passe sûr et rapide. Hacher un mot de passe un million de fois peut être plus sûr, mais aussi plus lent. Comment atteindre un bon équilibre entre vitesse et sécurité? De plus, je préférerais que le résultat ait un nombre constant de caractères.

  1. Le mécanisme de hachage doit être disponible en PHP
  2. Il doit être sûr
  3. Il peut utiliser du sel (dans ce cas, tous les sels sont-ils également bons? Existe-t-il un moyen de générer de bons sels?)

De plus, dois-je stocker deux champs dans la base de données (un utilisant MD5 et un autre utilisant SHA, par exemple)? Serait-il plus sûr ou moins sûr?

Au cas où je ne serais pas assez clair, je veux savoir quelle (s) fonction (s) de hachage utiliser et comment choisir un bon sel afin d'avoir un mécanisme de protection par mot de passe sûr et rapide.

Questions connexes qui ne couvrent pas tout à fait ma question:

Quelle est la différence entre SHA et MD5 dans PHP
Simple Password Encryption
Méthodes sécurisées de stockage des clés et des mots de passe pour asp.net
Comment implémenteriez-vous les mots de passe salés dans Tomcat 5.5


13
openwall.com/phpass est aussi une très bonne bibliothèque
Alfred

51
Md5 est maintenant complètement dangereux
JqueryToAddNumbers

3
@NSAwesomeGuy Cela dépend de l'utilisation que vous en faites. Il est trivial de faire correspondre arc-en-ciel ou simplement des mots de passe MD5 non salés à force brute, bien sûr, mais avec un salage décent, il est toujours extrêmement difficile de construire une table arc-en-ciel pour le craquage rapide d'ensembles de mots de passe, et la force brute est un no-hoper.
Craig Ringer

12
PHP 5.5+ a un hachage de mot de passe sécurisé intégré à php.net/manual/en/function.password-hash.php
Terence Johnson

Réponses:


982

AVERTISSEMENT : Cette réponse a été écrite en 2008.

Depuis lors, PHP nous a donné password_hashet password_verifyet, depuis leur introduction, ils sont les mots de passe a recommandé et méthode de vérification.

La théorie de la réponse reste cependant une bonne lecture.

TL; DR

À ne pas faire

  • Ne limitez pas les caractères que les utilisateurs peuvent saisir pour les mots de passe. Seuls les idiots le font.
  • Ne limitez pas la longueur d'un mot de passe. Si vos utilisateurs veulent une phrase contenant supercalifragilisticexpialidocious, ne les empêchez pas de l'utiliser.
  • Ne supprimez pas et n'échappez pas le HTML et les caractères spéciaux dans le mot de passe.
  • Ne stockez jamais le mot de passe de votre utilisateur en texte brut.
  • N'envoyez jamais de mot de passe à votre utilisateur, sauf s'il a perdu le sien et que vous en avez envoyé un temporairement.
  • Jamais, jamais enregistrer les mots de passe de quelque manière que ce soit.
  • Ne hachez jamais les mots de passe avec SHA1 ou MD5 ou même SHA256! Les crackers modernes peuvent dépasser 60 et 180 milliards de hachages / seconde (respectivement).
  • Ne mélangez pas bcrypt et avec la sortie brute de hash () , utilisez la sortie hexadécimale ou base64_encode. (Cela s'applique à toute entrée pouvant contenir un voyou \0, ce qui peut sérieusement affaiblir la sécurité.)

Dos

  • Utilisez scrypt quand vous le pouvez; bcrypt si vous ne pouvez pas.
  • Utilisez PBKDF2 si vous ne pouvez pas utiliser bcrypt ou scrypt, avec des hachages SHA2.
  • Réinitialisez les mots de passe de tout le monde lorsque la base de données est compromise.
  • Implémentez une longueur minimale raisonnable de 8 à 10 caractères, et exigez au moins 1 lettre majuscule, 1 lettre minuscule, un chiffre et un symbole. Cela améliorera l'entropie du mot de passe, ce qui le rendra plus difficile à déchiffrer. (Voir la section «Qu'est-ce qui fait un bon mot de passe?» Pour un débat.)

Pourquoi hacher les mots de passe de toute façon?

L'objectif derrière le hachage des mots de passe est simple: empêcher l'accès malveillant aux comptes d'utilisateurs en compromettant la base de données. Le but du hachage de mot de passe est donc de dissuader un pirate ou un pirate en leur coûtant trop de temps ou d'argent pour calculer les mots de passe en texte brut. Et le temps / coût sont les meilleurs moyens de dissuasion dans votre arsenal.

Une autre raison pour laquelle vous voulez un bon hachage robuste sur les comptes d'utilisateurs est de vous donner suffisamment de temps pour changer tous les mots de passe du système. Si votre base de données est compromise, vous aurez besoin de suffisamment de temps pour au moins verrouiller le système, sinon changer chaque mot de passe de la base de données.

Jeremiah Grossman, CTO de Whitehat Security, a déclaré sur le blog de White Hat Security après une récente récupération de mot de passe qui nécessitait une rupture par force brute de sa protection par mot de passe:

Fait intéressant, en vivant ce cauchemar, j'ai appris BEAUCOUP que je ne connaissais pas sur le craquage de mot de passe, le stockage et la complexité. J'en suis venu à comprendre pourquoi le stockage des mots de passe est toujours plus important que la complexité des mots de passe. Si vous ne savez pas comment votre mot de passe est stocké, alors tout ce dont vous pouvez vraiment compter est la complexité. Cela peut être une connaissance courante pour les professionnels du mot de passe et de la cryptographie, mais pour l'expert moyen d'InfoSec ou de la sécurité Web, j'en doute fortement.

(Je souligne.)

Qu'est-ce qui fait un bon mot de passe de toute façon?

Entropie . (Non pas que je souscrive pleinement au point de vue de Randall.)

En bref, l'entropie correspond à la variation du mot de passe. Lorsqu'un mot de passe n'est composé que de lettres romaines minuscules, cela ne représente que 26 caractères. Ce n'est pas beaucoup de variation. Les mots de passe alphanumériques sont meilleurs, avec 36 caractères. Mais autoriser les majuscules et les minuscules, avec des symboles, est d'environ 96 caractères. C'est bien mieux que de simples lettres. Un problème est que pour rendre nos mots de passe mémorables, nous insérons des modèles, ce qui réduit l'entropie. Oops!

L'entropie de mot de passe est approximée facilement. L'utilisation de la gamme complète de caractères ascii (environ 96 caractères typables) donne une entropie de 6,6 par caractère, ce qui à 8 caractères pour un mot de passe est encore trop faible (52,679 bits d'entropie) pour une sécurité future. Mais la bonne nouvelle est que les mots de passe plus longs et les mots de passe avec des caractères unicode augmentent vraiment l'entropie d'un mot de passe et le rendent plus difficile à déchiffrer.

Il y a une discussion plus longue sur l'entropie des mots de passe sur le site Crypto StackExchange . Une bonne recherche Google donnera également de nombreux résultats.

Dans les commentaires, j'ai parlé à @popnoodles, qui a souligné que l' application d' une politique de mot de passe de longueur X avec X nombreuses lettres, chiffres, symboles, etc., pouvait en fait réduire l'entropie en rendant le schéma de mot de passe plus prévisible. Je suis d'accord. L'aléatoire, aussi aléatoire que possible, est toujours la solution la plus sûre mais la moins mémorable.

Pour autant que j'ai pu le dire, créer le meilleur mot de passe au monde est un Catch-22. Soit ce n'est pas mémorable, trop prévisible, trop court, trop de caractères Unicode (difficile à taper sur un appareil Windows / Mobile), trop long, etc. Aucun mot de passe n'est vraiment assez bon pour nos besoins, nous devons donc les protéger comme s'ils étaient à Fort Knox.

Les meilleures pratiques

Bcrypt et scrypt sont les meilleures pratiques actuelles. Scrypt sera meilleur que bcrypt dans le temps, mais il n'a pas été adopté en tant que norme par Linux / Unix ou par les serveurs Web, et n'a pas encore fait l'objet d'un examen approfondi de son algorithme. Mais encore, l'avenir de l'algorithme semble prometteur. Si vous travaillez avec Ruby, il y a un joyau scrypt qui vous aidera et Node.js a maintenant son propre package scrypt . Vous pouvez utiliser Scrypt en PHP via l' extension Scrypt ou l' extension Libsodium (les deux sont disponibles dans PECL).

Je suggère fortement de lire la documentation de la fonction crypt si vous voulez comprendre comment utiliser bcrypt, ou vous trouver un bon wrapper ou utiliser quelque chose comme PHPASS pour une implémentation plus héritée. Je recommande un minimum de 12 tours de bcrypt, sinon 15 à 18.

J'ai changé d'avis sur l'utilisation de bcrypt lorsque j'ai appris que bcrypt utilise uniquement le calendrier des clés de blowfish, avec un mécanisme de coût variable. Ce dernier vous permet d'augmenter le coût de la force brute d'un mot de passe en augmentant le calendrier de clés déjà cher de Blowfish.

Pratiques moyennes

Je ne peux presque plus imaginer cette situation. PHPASS prend en charge PHP 3.0.18 à 5.3, il est donc utilisable sur presque toutes les installations imaginables et doit être utilisé si vous ne savez pas avec certitude que votre environnement prend en charge bcrypt.

Mais supposons que vous ne puissiez pas utiliser du tout bcrypt ou PHPASS. Et alors?

Essayez une implémentation de PDKBF2 avec le nombre maximal de tours que votre environnement / application / perception de l'utilisateur peut tolérer. Le nombre le plus bas que je recommanderais est de 2500 tours. Assurez-vous également d'utiliser hash_hmac () s'il est disponible pour rendre l'opération plus difficile à reproduire.

Pratiques futures

Venir en PHP 5.5 est une bibliothèque de protection par mot de passe complète qui résume toutes les difficultés de travailler avec bcrypt. Alors que la plupart d'entre nous sont bloqués avec PHP 5.2 et 5.3 dans la plupart des environnements courants, en particulier les hôtes partagés, @ircmaxell a construit une couche de compatibilité pour la prochaine API qui est rétrocompatible avec PHP 5.3.7.

Récapitulatif de la cryptographie et avis de non-responsabilité

La puissance de calcul requise pour réellement casser un mot de passe haché n'existe pas. La seule façon pour les ordinateurs de "casser" un mot de passe est de le recréer et de simuler l'algorithme de hachage utilisé pour le sécuriser. La vitesse du hachage est linéairement liée à sa capacité à être forcé par la force brute. Pire encore, la plupart des algorithmes de hachage peuvent être facilement parallélisés pour fonctionner encore plus rapidement. C'est pourquoi les schémas coûteux comme bcrypt et scrypt sont si importants.

Vous ne pouvez pas prévoir toutes les menaces ou voies d'attaque, et vous devez donc faire de votre mieux pour protéger vos utilisateurs à l'avance . Si vous ne le faites pas, vous pourriez même manquer le fait que vous avez été attaqué jusqu'à ce qu'il soit trop tard ... et vous êtes responsable . Pour éviter cette situation, agissez paranoïaque pour commencer. Attaquez votre propre logiciel (en interne) et tentez de voler les informations d'identification de l'utilisateur, ou de modifier les comptes d'autres utilisateurs ou d'accéder à leurs données. Si vous ne testez pas la sécurité de votre système, vous ne pouvez blâmer personne d'autre que vous-même.

Enfin: je ne suis pas cryptographe. Tout ce que j'ai dit, c'est mon opinion, mais je pense que c'est basé sur le bon vieux bon sens ... et beaucoup de lecture. N'oubliez pas, soyez aussi paranoïaque que possible, rendez les choses aussi difficiles à empiéter que possible, puis, si vous êtes toujours inquiet, contactez un pirate à chapeau blanc ou un cryptographe pour voir ce qu'ils disent de votre code / système.


9
un secret n'aide pas car votre base de données de mots de passe est censée être secrète de toute façon - s'ils peuvent mettre la main sur cette base de données, ils peuvent également trouver le secret que vous utilisez. il est cependant important que le sel soit aléatoire.
frankodwyer

2
notez, il n'est pas vraiment vrai que «la puissance de calcul pour décrypter» n'existe pas encore. comme la plupart des mots de passe sont des mots de dictionnaire ou dérivés d'un dictionnaire, une attaque basée sur un dictionnaire est généralement très efficace (d'où l'utilisation de politiques de mot de passe et de décomptes d'itérations).
frankodwyer

6
@ puce piquée, je ne discute pas avec toi. Je souligne simplement à quel point ce domaine de notre travail est compliqué et complexe. J'espère toujours être formé par les meilleures pratiques les plus intelligentes pour mettre en place un système de gestion de contenu pour un petit site Web. J'apprends encore ici. ... chaque fois que je lis quelque chose qui a du sens, je remarque bientôt 5 autres articles qui le contredisent. ce tour-et-rond devient vertigineux rapidement :)
m42

4
Révision intéressante. L'ID utilisateur (par exemple, un incrément automatique BIGINT) est-il un bon nonce? Ou comme ce n'est pas aléatoire, ce n'est pas bon? De plus, je vais devoir stocker le nonce pour chaque utilisateur dans la base de données ... La clé de site + nonce + HMAC offre-t-elle une sécurité améliorée significative sur un hachage salé (avec ID utilisateur) itéré plusieurs fois? De même, l'itération de HMAC plusieurs fois est-elle bonne pour la sécurité?
luiscubal

4
L'envoi d'un mot de passe temporaire par e-mail qui nécessite que l'utilisateur le change la première fois qu'il l'utilise et l'envoi d'un lien "sécurisé" par e-mail qui lui permet de définir son mot de passe sont tout aussi risqués. Dans les deux cas, toute personne qui intercepte l'e-mail peut accéder au compte tant qu'elle utilise le lien ou le mot de passe avant le destinataire prévu.
Tim Gautier

138

Une réponse beaucoup plus courte et plus sûre - n'écrivez pas du tout votre propre mécanisme de mot de passe , utilisez un mécanisme éprouvé.

  • PHP 5.5 ou supérieur: password_hash () est de bonne qualité et fait partie du noyau PHP.
  • Versions PHP plus anciennes: la bibliothèque phpass d' OpenWall est bien meilleure que la plupart des codes personnalisés - utilisés dans WordPress, Drupal, etc.

La plupart des programmeurs n'ont tout simplement pas l'expertise nécessaire pour écrire du code lié à la cryptographie en toute sécurité sans introduire de vulnérabilités.

Auto-test rapide: qu'est-ce que l'étirement des mots de passe et combien d'itérations devez-vous utiliser? Si vous ne connaissez pas la réponse, vous devriez l'utiliser password_hash(), car l'étirement des mots de passe est désormais une caractéristique essentielle des mécanismes de mot de passe en raison de processeurs beaucoup plus rapides et de l'utilisation de GPU et FPGA pour casser les mots de passe à des taux de milliards de suppositions par seconde (avec les GPU ).

Par exemple, vous pouvez casser tous les mots de passe Windows à 8 caractères en 6 heures en utilisant 25 GPU installés sur 5 PC de bureau. Il s'agit d'un forçage brut, c'est-à-dire d'énumérer et de vérifier chaque mot de passe Windows à 8 caractères , y compris les caractères spéciaux, et ce n'est pas une attaque par dictionnaire. C'était en 2012, à partir de 2018, vous pouviez utiliser moins de GPU ou craquer plus rapidement avec 25 GPU.

Il existe également de nombreuses attaques de table arc-en-ciel sur les mots de passe Windows qui s'exécutent sur des processeurs ordinaires et sont très rapides. Tout cela est parce que Windows encore ne pas le sel ou étirer ses mots de passe, même dans Windows 10 - ne faites pas la même erreur que Microsoft a fait!

Voir également:

  • excellente réponse avec plus sur pourquoi password_hash()ou phpasssont la meilleure façon de procéder.
  • bon article de blog donnant des «facteurs de travail» recommandés (nombre d'itérations) pour les principaux algorithmes, y compris bcrypt, scrypt et PBKDF2.

1
mais ces systèmes sont mieux connus et peut-être déjà compromis. mais il vaut mieux faire votre propre quand vous ne savez pas ce que vous faites.
JqueryToAddNumbers

14
Re "ces systèmes sont mieux connus et peut-être déjà compromis" - il n'y a aucune raison pour qu'un système bien conçu pour l'authentification devienne "déjà compromis" simplement parce qu'il est mieux connu. Des bibliothèques telles que phpass sont écrites par des experts et examinées en détail par de nombreuses personnes - le fait qu'elles soient bien connues va de pair avec un examen détaillé par différentes personnes et est plus susceptible de signifier qu'elles sont sécurisées.
RichVel

Compte tenu des récents vidages de hachage de mot de passe de LinkedIn, Last.fm et d'autres, c'est assez d'actualité. Vous êtes en bonne compagnie en ne sachant pas comment écrire votre propre mécanisme de mot de passe!
RichVel

3
@PP - les chances d'un algorithme de hachage de mot de passe évalué par les pairs ayant une porte dérobée NSA sont très faibles, à mon avis. Les chances que quelqu'un qui n'est pas un véritable expert en cryptographie écrive un nouveau mécanisme de hachage de mot de passe sans autres vulnérabilités sont beaucoup plus faibles. Et la webapp typique utilise uniquement le hachage MD5 ou SHA-1, ce qui est terrible - même le très bon livre Essential Chris Security de Chris Shiflett recommande MD5 ...
RichVel

1
@RichVel - La fonction password_hash (). Comme mentionné précédemment, il est intégré au noyau PHP (aka / ext / standard).
CubicleSoft

43

Je ne stockerais pas le mot de passe haché de deux manières différentes, car alors le système est au moins aussi faible que le plus faible des algorithmes de hachage utilisés.


pas pour le hachage de mot de passe. l'attaquant n'a besoin que de casser un hachage pour récupérer le mot de passe. le point est de toute façon théorique puisque ni MD5 ni SHA1 n'ont de coupures pratiques disponibles dans le scénario de mot de passe.
frankodwyer

2
désolé, j'ai mal lu votre réponse en recommandant d'utiliser deux hachages ... vous avez en fait raison. L'utilisation de deux hachages affaiblit le système dans le cas du mot de passe, car ils n'ont besoin que de casser le hachage le plus faible.
frankodwyer

40

Depuis PHP 5.5, PHP dispose de fonctions simples et sécurisées pour hacher et vérifier les mots de passe, password_hash () et password_verify ()

$password = 'anna';
$hash = password_hash($password, PASSWORD_DEFAULT);
$expensiveHash = password_hash($password, PASSWORD_DEFAULT, array('cost' => 20));

password_verify('anna', $hash); //Returns true
password_verify('anna', $expensiveHash); //Also returns true
password_verify('elsa', $hash); //Returns false

Lorsqu'il password_hash()est utilisé, il génère un sel aléatoire et l'inclut dans le hachage en sortie (avec le coût et l'algorithme utilisé.) password_verify()Puis lit ce hachage et détermine le sel et la méthode de cryptage utilisés, et le vérifie par rapport au mot de passe en clair fourni.

Fournir l' PASSWORD_DEFAULTinstruction PHP d'utiliser l'algorithme de hachage par défaut de la version installée de PHP. Exactement quel algorithme que cela signifie est destiné à changer au fil du temps dans les futures versions, de sorte qu'il sera toujours l'un des algorithmes les plus puissants disponibles.

L'augmentation du coût (par défaut à 10) rend le hachage plus difficile à utiliser par force brute, mais signifie également que générer des hachages et vérifier les mots de passe par rapport à eux sera plus de travail pour le processeur de votre serveur.

Notez que même si l'algorithme de hachage par défaut peut changer, les anciens hachages continueront à vérifier très bien car l'algorithme utilisé est stocké dans le hachage et le password_verify()reprend.


33

Bien que la question ait été répondue, je veux juste réitérer que les sels utilisés pour le hachage doivent être aléatoires et non pas comme l'adresse e-mail comme suggéré dans la première réponse.

Plus d'explications sont disponibles sur- http://www.pivotalsecurity.com/blog/password-hashing-salt-should-it-be-random/

Récemment, j'ai eu une discussion pour savoir si les hachages de mot de passe salés avec des bits aléatoires sont plus sûrs que celui salé avec des sels devinables ou connus. Voyons voir: Si le système stockant le mot de passe est compromis ainsi que le système qui stocke le sel aléatoire, l'attaquant aura accès au hachage ainsi qu'au sel, donc que le sel soit aléatoire ou non, peu importe. L'attaquant peut générer des tables arc-en-ciel pré-calculées pour casser le hachage. Voici la partie intéressante - il n'est pas si simple de générer des tables pré-calculées. Prenons l'exemple du modèle de sécurité WPA. Votre mot de passe WPA n'est en fait jamais envoyé au point d'accès sans fil. Au lieu de cela, il est haché avec votre SSID (le nom de réseau Linksys, Dlink, etc.). Une très bonne explication de la façon dont cela fonctionne est ici. Pour récupérer le mot de passe du hachage, vous aurez besoin de connaître le mot de passe ainsi que salt (nom du réseau). Church of Wifi a déjà pré-calculé des tables de hachage qui contiennent les 1000 premiers SSID et environ 1 million de mots de passe. La taille de toutes les tables est d'environ 40 Go. Comme vous pouvez le lire sur leur site, quelqu'un a utilisé 15 tableaux FGPA pendant 3 jours pour générer ces tableaux. En supposant que la victime utilise le SSID comme «a387csf3» et le mot de passe comme «123456», sera-t-il craqué par ces tables? Non! .. ça ne peut pas. Même si le mot de passe est faible, les tables n'ont pas de hachage pour le SSID a387csf3. C'est la beauté d'avoir du sel au hasard. Cela dissuadera les crackers qui prospèrent sur les tables pré-calculées. Peut-il arrêter un pirate déterminé? Probablement pas. Mais l'utilisation de sels aléatoires fournit une couche de défense supplémentaire. Pendant que nous sommes sur ce sujet, laissez-nous discuter de l'avantage supplémentaire de stocker des sels aléatoires sur un système séparé. Scénario n ° 1: les hachages de mot de passe sont stockés sur le système X et les valeurs de sel utilisées pour le hachage sont stockées sur le système Y. Ces valeurs de sel sont devinables ou connues (par exemple, nom d'utilisateur) Scénario n ° 2: les hachages de mot de passe sont stockés sur le système X et les valeurs de sel utilisées pour les hachages sont stockés sur le système Y. Ces valeurs de sel sont aléatoires. Dans le cas où le système X a été compromis, comme vous pouvez le deviner, il y a un énorme avantage à utiliser du sel aléatoire sur un système séparé (scénario 2). L'attaquant devra deviner les valeurs d'addition pour pouvoir cracker les hachages. Si un sel 32 bits est utilisé, 2 ^ 32 = 4 294 967 296 (environ 4,2 milliards) d'itérations peuvent être nécessaires pour chaque mot de passe deviné. Les hachages de mot de passe sont stockés sur le système X et les valeurs de sel utilisées pour le hachage sont stockées sur le système Y. Ces valeurs de sel sont devinables ou connues (par exemple, nom d'utilisateur) Scénario n ° 2: les hachages de mot de passe sont stockés sur le système X et les valeurs de sel utilisées pour le hachage sont stockées sur système Y. Ces valeurs de sel sont aléatoires. Dans le cas où le système X a été compromis, comme vous pouvez le deviner, il y a un énorme avantage à utiliser du sel aléatoire sur un système séparé (scénario 2). L'attaquant devra deviner les valeurs d'addition pour pouvoir cracker les hachages. Si un sel 32 bits est utilisé, 2 ^ 32 = 4 294 967 296 (environ 4,2 milliards) d'itérations peuvent être nécessaires pour chaque mot de passe deviné. Les hachages de mot de passe sont stockés sur le système X et les valeurs de sel utilisées pour le hachage sont stockées sur le système Y. Ces valeurs de sel sont devinables ou connues (par exemple, nom d'utilisateur) Scénario n ° 2: les hachages de mot de passe sont stockés sur le système X et les valeurs de sel utilisées pour le hachage sont stockées sur système Y. Ces valeurs de sel sont aléatoires. Dans le cas où le système X a été compromis, comme vous pouvez le deviner, il y a un énorme avantage à utiliser du sel aléatoire sur un système séparé (scénario 2). L'attaquant devra deviner les valeurs d'addition pour pouvoir cracker les hachages. Si un sel 32 bits est utilisé, 2 ^ 32 = 4 294 967 296 (environ 4,2 milliards) d'itérations peuvent être nécessaires pour chaque mot de passe deviné. Ces valeurs de sel sont aléatoires. Dans le cas où le système X a été compromis, comme vous pouvez le deviner, il y a un énorme avantage à utiliser du sel aléatoire sur un système séparé (scénario 2). L'attaquant devra deviner les valeurs d'addition pour pouvoir cracker les hachages. Si un sel 32 bits est utilisé, 2 ^ 32 = 4 294 967 296 (environ 4,2 milliards) d'itérations peuvent être nécessaires pour chaque mot de passe deviné. Ces valeurs de sel sont aléatoires. Dans le cas où le système X a été compromis, comme vous pouvez le deviner, il y a un énorme avantage à utiliser du sel aléatoire sur un système séparé (scénario 2). L'attaquant devra deviner les valeurs d'addition pour pouvoir cracker les hachages. Si un sel 32 bits est utilisé, 2 ^ 32 = 4 294 967 296 (environ 4,2 milliards) d'itérations peuvent être nécessaires pour chaque mot de passe deviné.


7
Même si l'attaquant obtient le sel, une chaîne "sitesalt: usersalt: password" est toujours résistante aux tables précalculées, car l'attaquant doit générer les tables pour chaque utilisateur (donc l'attaque devient beaucoup plus lente), à ​​moins bien sûr qu'un utilisateur spécifique est ciblé ...
luiscubal

Concernant "Même si l'attaquant obtient le sel, une chaîne" sitesalt: usersalt: password "est toujours résistante aux tables précalculées", totalement d'accord. Mon point est que sitesalt, s'il est rendu aléatoire et long, rendra le système plus sûr qu'il (sitesalt) étant prévisible. J'ai vu des gens recommander l'utilisation de l'identifiant e-mail, etc. comme sel, et je décourage cela.
Gaurav Kumar

Vous avez manqué ce que j'ai écrit à l'origine. J'ai dit d'utiliser un nonce aléatoire, stocké avec le dossier, PLUS l'adresse e-mail. L'ajout de l'adresse e-mail rend l'entropie supplémentaire sur laquelle le pirate peut travailler. J'ai depuis réécrit ma réponse en faveur de bcrypt.
Robert K

28

Je veux juste souligner que PHP 5.5 inclut une API de hachage de mot de passe qui fournit un wrapper crypt(). Cette API simplifie considérablement la tâche de hachage, de vérification et de remaniement des hachages de mot de passe. L'auteur a également publié un pack de compatibilité (sous la forme d'un seul fichier password.php que vous devez simplement requireutiliser), pour ceux qui utilisent PHP 5.3.7 et versions ultérieures et qui souhaitent l'utiliser dès maintenant.

Il ne prend en charge que BCRYPT pour l'instant, mais il vise à être facilement étendu pour inclure d'autres techniques de hachage de mot de passe et parce que la technique et le coût sont stockés dans le cadre du hachage, les modifications apportées à votre technique / coût de hachage préféré n'invalideront pas les hachages actuels, le cadre utilisera automatiquement la technique / le coût correct lors de la validation. Il gère également la génération d'un sel «sécurisé» si vous ne définissez pas explicitement le vôtre.

L'API expose quatre fonctions:

  • password_get_info() - renvoie des informations sur le hachage donné
  • password_hash() - crée un hachage de mot de passe
  • password_needs_rehash()- vérifie si le hachage donné correspond aux options données. Utile pour vérifier si le hachage est conforme à votre schéma technique / coût actuel, vous permettant de ressasser si nécessaire
  • password_verify() - vérifie qu'un mot de passe correspond à un hachage

Pour le moment, ces fonctions acceptent les constantes de mot de passe PASSWORD_BCRYPT et PASSWORD_DEFAULT, qui sont actuellement synonymes, la différence étant que PASSWORD_DEFAULT "peut changer dans les versions PHP plus récentes lorsque des algorithmes de hachage plus récents et plus forts sont pris en charge". L'utilisation de PASSWORD_DEFAULT et de password_needs_rehash () lors de la connexion (et ressassement si nécessaire) devrait garantir que vos hachages sont raisonnablement résistants aux attaques par force brute avec peu ou pas de travail pour vous.

EDIT: Je viens de réaliser que cela est mentionné brièvement dans la réponse de Robert K. Je vais laisser cette réponse ici car je pense qu'elle fournit un peu plus d'informations sur son fonctionnement et sa facilité d'utilisation pour ceux qui ne connaissent pas la sécurité.


19

J'utilise Phpass qui est une simple classe PHP à un fichier qui pourrait être implémentée très facilement dans presque tous les projets PHP. Voir aussi la H .

Par défaut, il a utilisé le cryptage le plus puissant disponible qui est implémenté dans Phpass, qui est bcryptet revient à d'autres cryptages jusqu'à MD5 pour fournir une compatibilité descendante avec des frameworks comme Wordpress.

Le hachage retourné peut être stocké dans la base de données tel quel. Exemple d'utilisation pour générer du hachage:

$t_hasher = new PasswordHash(8, FALSE);
$hash = $t_hasher->HashPassword($password);

Pour vérifier le mot de passe, on peut utiliser:

$t_hasher = new PasswordHash(8, FALSE);
$check = $t_hasher->CheckPassword($password, $hash);

14

CHOSES À RETENIR

Beaucoup a été dit sur le cryptage de mot de passe pour PHP, dont la plupart sont de très bons conseils, mais avant même de commencer le processus d'utilisation de PHP pour le cryptage de mot de passe, assurez-vous que les éléments suivants sont implémentés ou prêts à être implémentés.

SERVEUR

PORTS

Peu importe la qualité de votre cryptage, si vous ne sécurisez pas correctement le serveur qui exécute PHP et DB, tous vos efforts ne valent rien. La plupart des serveurs fonctionnent relativement de la même manière, ils ont des ports attribués pour vous permettre d'y accéder à distance via ftp ou shell. Assurez-vous de modifier le port par défaut dont vous avez activé la connexion à distance. En ne faisant pas cela, vous avez en fait obligé l'attaquant à faire un pas de plus pour accéder à votre système.

NOM D'UTILISATEUR

Pour tout ce qui est bon dans le monde, n'utilisez pas le nom d'utilisateur admin, root ou quelque chose de similaire. De plus, si vous êtes sur un système basé sur Unix, NE Rendez PAS la connexion au compte root accessible, elle doit toujours être sudo uniquement.

MOT DE PASSE

Vous dites à vos utilisateurs de faire de bons mots de passe pour éviter d'être piraté, faites de même. Quel est l'intérêt de passer par tous les efforts de verrouillage de votre porte d'entrée lorsque la porte arrière est grande ouverte.

BASE DE DONNÉES

SERVEUR

Idéalement, vous voulez que votre base de données et votre application sur des serveurs distincts. Ce n'est pas toujours possible en raison du coût, mais cela permet une certaine sécurité car l'attaquant devra passer par deux étapes pour accéder pleinement au système.

UTILISATEUR

Votre application doit toujours avoir son propre compte pour accéder à la base de données et ne lui accorder que les privilèges dont elle aura besoin.

Ensuite, ayez un compte utilisateur distinct pour vous qui n'est stocké nulle part sur le serveur, même pas dans l'application.

Comme toujours, NE faites PAS cette racine ou quelque chose de similaire.

MOT DE PASSE

Suivez les mêmes directives que pour tous les bons mots de passe. De plus, ne réutilisez pas le même mot de passe sur aucun compte SERVER ou DB sur le même système.

PHP

MOT DE PASSE

NE JAMAIS stocker un mot de passe dans votre base de données, mais plutôt stocker le hachage et le sel unique, je vous expliquerai pourquoi plus tard.

HACHAGE

ONE WAY HASHING! de la même manière et comparez les deux hachages. Cela signifie que même si un attaquant a accès à la base de données, il ne sait pas quel est réellement le mot de passe, juste son hachage résultant. Ce qui signifie plus de sécurité pour vos utilisateurs dans le pire scénario possible.

Il y a beaucoup de bonnes fonctions de hachage là - bas ( password_hash, hash, etc ...) mais vous devez choisir un bon algorithme pour le hachage pour être efficace. (bcrypt et ceux qui lui sont similaires sont des algorithmes décents.)

Lorsque la vitesse de hachage est la clé, le plus lent est le plus résistant aux attaques Brute Force.

L'une des erreurs les plus courantes dans le hachage est que les hachages ne sont pas uniques aux utilisateurs. Cela est principalement dû au fait que les sels ne sont pas générés de manière unique.

SALAISON

Les mots de passe doivent toujours être salés avant d'être hachés. Salting ajoute une chaîne aléatoire au mot de passe afin que les mots de passe similaires n'apparaissent pas de la même manière dans la base de données. Cependant, si le sel n'est pas unique à chaque utilisateur (c'est-à-dire: vous utilisez un sel codé en dur), vous avez pratiquement rendu votre sel sans valeur. Parce qu'une fois qu'un attaquant a trouvé un sel de mot de passe, il a le sel pour chacun d'eux.

Lorsque vous créez un sel, assurez-vous qu'il est unique au mot de passe qu'il salte, puis stockez le hachage et le sel terminés dans votre base de données. Ce que cela fera, c'est de faire en sorte qu'un attaquant doive casser individuellement chaque sel et hachage avant de pouvoir y accéder. Cela signifie beaucoup plus de travail et de temps pour l'attaquant.

UTILISATEURS CRÉANT DES MOTS DE PASSE

Si l'utilisateur crée un mot de passe via le frontend, cela signifie qu'il doit être envoyé au serveur. Cela ouvre un problème de sécurité car cela signifie que le mot de passe non crypté est envoyé au serveur et si un attaquant est capable d'écouter et d'accéder à ce que toute votre sécurité en PHP ne vaut rien. TOUJOURS transmettre les données en toute sécurité, cela se fait via SSL, mais soyez las même SSL n'est pas sans faille (la faille Heartbleed d'OpenSSL en est un exemple).

Demandez également à l'utilisateur de créer un mot de passe sécurisé, c'est simple et devrait toujours être fait, l'utilisateur en sera reconnaissant à la fin.

Enfin, peu importe les mesures de sécurité que vous prenez, rien n'est sûr à 100%, plus la technologie à protéger est avancée, plus les attaques deviennent avancées. Mais suivre ces étapes rendra votre site plus sécurisé et beaucoup moins souhaitable pour les attaquants.

Voici une classe PHP qui crée facilement un hachage et du sel pour un mot de passe

http://git.io/mSJqpw


1
Vous devez supprimer SHA512 de votre liste d'algorithmes de hachage décents, car il est trop rapide. Utilisez-le uniquement en combinaison avec PBKDF2. Alors que BCrypt est basé sur Blowfish, Blowfish lui-même est un algorithme de chiffrement, pas de hachage.
martinstoeckli

1
Comment stockez-vous le sel aléatoire dans la DB? Je pense que vous ne le hachez pas (ne peut pas être utilisé pour la vérification) ni ne le stockez en clair (aucun avantage réel si l'attaquant peut lire la base de données). Alors, comment tu fais?
Iazel

wmfrancia a écrit: "Salting ajoute une chaîne aléatoire au mot de passe afin que les mots de passe similaires n'apparaissent pas les mêmes dans la base de données". Cela n'a pas de sens pour moi. Les hachages dans la base de données sembleront déjà différents car c'est une propriété des fonctions de hachage.
H2ONaCl

wmfancia a écrit à propos d'un sel constant: "une fois qu'un attaquant a trouvé un sel de mot de passe, il a le sel pour tous". La même chose peut être dite que si le pirate détermine quel champ DB est le sel, il a les sels pour chacun d'eux. Puisqu'un sel constant ne serait probablement pas dans la DB, c'est une bonne chose à propos d'un sel constant.
H2ONaCl

Bien sûr, ces commentaires ne suggèrent pas qu'un sel aléatoire par utilisateur n'est pas meilleur qu'un sel par application. Il est préférable.
H2ONaCl

12

Google dit que SHA256 est disponible pour PHP.

Vous devez absolument utiliser un sel. Je recommanderais d'utiliser des octets aléatoires (et ne vous limitez pas aux caractères et aux chiffres). Comme d'habitude, plus vous choisissez, plus il est sûr et lent. 64 octets devraient être corrects, je suppose.


13
64 bits devraient être suffisants pour n'importe qui?
Konerak

@Konerak, j'y reviendrais après 20 ans. :) Mais oui SHA256 est en effet disponible. Si vous voulez savoir à quel point SHA256 est sécurisé, vous pouvez le vérifier: security.stackexchange.com/questions/90064/…
Vincent Edward Gedaria Binua

8

Au final, le double hachage, mathématiquement, n'apporte aucun avantage. En pratique, cependant, il est utile pour prévenir les attaques basées sur la table arc-en-ciel. En d'autres termes, il n'est pas plus avantageux que le hachage avec un sel, ce qui prend beaucoup moins de temps processeur dans votre application ou sur votre serveur.


2
le hachage multiple protège également contre les attaques par dictionnaire et par force brute - c'est-à-dire qu'il les rend simplement plus longues à calculer.
frankodwyer

6
le double hachage ne vous donnera pas un avantage significatif, mais les itérations de hachage multi-tours sont toujours une défense possible contre les attaques par dictionnaire et par force de bruce. Les hachages de mots de passe de qualité industrielle utilisent plus de 1000 tours. PBKDF1 de PKCS # 5 suggère 1000 tours minimum.
Berk D. Demir

8

J'ai trouvé un sujet parfait à ce sujet ici: https://crackstation.net/hashing-security.htm , je voulais que vous en profitiez, voici également le code source qui prévient également les attaques basées sur le temps.

<?php
/*
 * Password hashing with PBKDF2.
 * Author: havoc AT defuse.ca
 * www: https://defuse.ca/php-pbkdf2.htm
 */

// These constants may be changed without breaking existing hashes.
define("PBKDF2_HASH_ALGORITHM", "sha256");
define("PBKDF2_ITERATIONS", 1000);
define("PBKDF2_SALT_BYTES", 24);
define("PBKDF2_HASH_BYTES", 24);

define("HASH_SECTIONS", 4);
define("HASH_ALGORITHM_INDEX", 0);
define("HASH_ITERATION_INDEX", 1);
define("HASH_SALT_INDEX", 2);
define("HASH_PBKDF2_INDEX", 3);

function create_hash($password)
{
    // format: algorithm:iterations:salt:hash
    $salt = base64_encode(mcrypt_create_iv(PBKDF2_SALT_BYTES, MCRYPT_DEV_URANDOM));
    return PBKDF2_HASH_ALGORITHM . ":" . PBKDF2_ITERATIONS . ":" .  $salt . ":" . 
        base64_encode(pbkdf2(
            PBKDF2_HASH_ALGORITHM,
            $password,
            $salt,
            PBKDF2_ITERATIONS,
            PBKDF2_HASH_BYTES,
            true
        ));
}

function validate_password($password, $good_hash)
{
    $params = explode(":", $good_hash);
    if(count($params) < HASH_SECTIONS)
       return false; 
    $pbkdf2 = base64_decode($params[HASH_PBKDF2_INDEX]);
    return slow_equals(
        $pbkdf2,
        pbkdf2(
            $params[HASH_ALGORITHM_INDEX],
            $password,
            $params[HASH_SALT_INDEX],
            (int)$params[HASH_ITERATION_INDEX],
            strlen($pbkdf2),
            true
        )
    );
}

// Compares two strings $a and $b in length-constant time.
function slow_equals($a, $b)
{
    $diff = strlen($a) ^ strlen($b);
    for($i = 0; $i < strlen($a) && $i < strlen($b); $i++)
    {
        $diff |= ord($a[$i]) ^ ord($b[$i]);
    }
    return $diff === 0; 
}

/*
 * PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt
 * $algorithm - The hash algorithm to use. Recommended: SHA256
 * $password - The password.
 * $salt - A salt that is unique to the password.
 * $count - Iteration count. Higher is better, but slower. Recommended: At least 1000.
 * $key_length - The length of the derived key in bytes.
 * $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise.
 * Returns: A $key_length-byte key derived from the password and salt.
 *
 * Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt
 *
 * This implementation of PBKDF2 was originally created by https://defuse.ca
 * With improvements by http://www.variations-of-shadow.com
 */
function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
{
    $algorithm = strtolower($algorithm);
    if(!in_array($algorithm, hash_algos(), true))
        die('PBKDF2 ERROR: Invalid hash algorithm.');
    if($count <= 0 || $key_length <= 0)
        die('PBKDF2 ERROR: Invalid parameters.');

    $hash_length = strlen(hash($algorithm, "", true));
    $block_count = ceil($key_length / $hash_length);

    $output = "";
    for($i = 1; $i <= $block_count; $i++) {
        // $i encoded as 4 bytes, big endian.
        $last = $salt . pack("N", $i);
        // first iteration
        $last = $xorsum = hash_hmac($algorithm, $last, $password, true);
        // perform the other $count - 1 iterations
        for ($j = 1; $j < $count; $j++) {
            $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true));
        }
        $output .= $xorsum;
    }

    if($raw_output)
        return substr($output, 0, $key_length);
    else
        return bin2hex(substr($output, 0, $key_length));
}
?>

Vous nous donnez une solution sans aucune utilisation sans utilisation
Michael

6

J'utilise généralement SHA1 et salt avec l'ID utilisateur (ou une autre information spécifique à l'utilisateur), et parfois j'utilise également un sel constant (j'ai donc 2 parties pour le sel).

SHA1 est désormais également considéré comme quelque peu compromis, mais dans une bien moindre mesure que MD5. En utilisant un sel (n'importe quel sel), vous empêchez l'utilisation d'une table arc- en -ciel générique pour attaquer vos hachages (certaines personnes ont même réussi à utiliser Google comme une sorte de table arc-en-ciel en recherchant le hachage). Un attaquant pourrait éventuellement générer une table arc-en-ciel en utilisant votre sel, c'est pourquoi vous devriez inclure un sel spécifique à l'utilisateur. De cette façon, ils devront générer une table arc-en-ciel pour chaque enregistrement de votre système, pas seulement un pour l'ensemble de votre système! Avec ce type de salage, même le MD5 est décemment sécurisé.


2
le sel constant n'est pas une bonne idée ... probablement pas un défaut fatal mais il affaiblit inutilement le schéma.
frankodwyer

MD5 et SHA1 sont rapides, c'est donc une mauvaise idée.
CodesInChaos

4

SHA1 et un sel devraient suffire (selon, naturellement, si vous codez quelque chose pour Fort Knox ou un système de connexion pour votre liste de courses) dans un avenir prévisible. Si SHA1 ne vous convient pas, utilisez SHA256 .

L'idée d'un sel est de déséquilibrer les résultats de hachage, pour ainsi dire. Il est connu, par exemple, que le hachage MD5 d'une chaîne vide est d41d8cd98f00b204e9800998ecf8427e. Donc, si quelqu'un avec suffisamment de mémoire voit ce hachage et sait que c'est le hachage d'une chaîne vide. Mais si la chaîne est salée (par exemple, avec la chaîne " MY_PERSONAL_SALT"), le hachage de la "chaîne vide" (c'est-à-dire " MY_PERSONAL_SALT") devient aeac2612626724592271634fb14d3ea6, donc non évident à revenir en arrière. Ce que je suis en train de dire qu'il est préférable d'utiliser tout sel, que de ne pas. Par conséquent, il n'est pas trop important de savoir quel sel utiliser.

Il existe en fait des sites Web qui font exactement cela - vous pouvez lui fournir un hachage (md5), et il crache un texte en clair connu qui génère ce hachage particulier. Si vous pouviez accéder à une base de données qui stocke des hachages md5 simples, il serait trivial pour vous d'entrer le hachage pour l'administrateur d'un tel service et de vous connecter. Mais, si les mots de passe étaient salés, un tel service deviendrait inefficace.

En outre, le double hachage est généralement considéré comme une mauvaise méthode, car il diminue l'espace de résultat. Tous les hachages populaires sont à longueur fixe. Ainsi, vous ne pouvez avoir qu'une valeur finie de cette longueur fixe et les résultats deviennent moins variés. Cela pourrait être considéré comme une autre forme de salage, mais je ne le recommanderais pas.


Le site cible ne doit rien contenir de trop sensible (ce n'est pas une banque), mais je préfère quand même le sécuriser.
luiscubal

1
le double hachage ne réduit pas l'espace des résultats. Le hachage itératif est un contrôle commun contre les attaques par dictionnaire et par force brute (il les ralentit beaucoup plus qu'il ne ralentit la vérification de votre mot de passe).
frankodwyer

2
@frankodwyer: oui, c'est mauvais. sha1(sha1($foo))réduit efficacement l'espace de sortie, car toute collision de la fonction intérieure deviendra automatiquement une collision de la fonction extérieure. La dégradation est linéaire, mais c'est toujours une préoccupation. Les méthodes de hachage itératives réinjectent des données à chaque tour, telles que $hash = sha1(sha1($salt . $password) . $salt). Mais ce n'est toujours pas bon ... Restez avec PBKDF2 ou Bcrypt ...
ircmaxell

-7

ok dans le fit, nous avons besoin de sel de sel doit être unique alors laissez-le générer

   /**
     * Generating string
     * @param $size
     * @return string
     */
    function Uniwur_string($size){
        $text = md5(uniqid(rand(), TRUE));
        RETURN substr($text, 0, $size);
    }

nous avons aussi besoin du hachage que j'utilise sha512 c'est le meilleur et c'est en php

   /**
     * Hashing string
     * @param $string
     * @return string
     */
    function hash($string){
        return hash('sha512', $string);
    }

maintenant nous pouvons utiliser ces fonctions pour générer un mot de passe sûr

// generating unique password
$password = Uniwur_string(20); // or you can add manual password
// generating 32 character salt
$salt = Uniwur_string(32);
// now we can manipulate this informations

// hashin salt for safe
$hash_salt = hash($salt);
// hashing password
$hash_psw = hash($password.$hash_salt);

maintenant, nous devons enregistrer dans la base de données notre valeur de variable $ hash_psw et la variable $ salt

et pour autoriser, nous utiliserons les mêmes étapes ...

c'est le meilleur moyen de sécuriser les mots de passe de nos clients ...

Ps pour les 2 dernières étapes, vous pouvez utiliser votre propre algorithme ... mais assurez-vous de pouvoir générer ce mot de passe haché à l'avenir lorsque vous devrez autoriser l'utilisateur ...


4
Cette question concernait les hachages pour les mots de passe. 1 l'exécution sha512(même salée) est largement considérée comme insuffisante pour la protection par mot de passe. (également que RNG n'est pas cryptographiquement sécurisé, donc l'utiliser pour la génération de mot de passe est risqué).
luiscubal

2
Tu n'as aucune idée de ce que tu fais. Lisez les meilleures réponses dans ce post et vous pouvez voir pourquoi votre code n'est pas seulement non sécurisé, mais n'a aucun sens.
cryptique

D'accord. mon code n'est pas sécurisé. alors laissez-moi savoir pourquoi utilisez-vous dans vos algorithmes ony sha256 ??? Je sais que sha512 est le meilleur pourquoi ne pas l'utiliser ???
shalvasoft

1
@shalvasoft sha512 est assez bon pour le hachage à usage général, mais la protection par mot de passe nécessite des hachages avec des propriétés très spécifiques ("être lent" est étrangement une bonne chose , par exemple, et sha512 est assez rapide). Certaines personnes ont utilisé sha512 comme un bloc de construction pour créer des fonctions de hachage de mot de passe, mais de nos jours l'approche recommandée est "utilisez bcrypt et gardez un œil sur scrypt".
luiscubal
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.