Vaut-il la peine de hacher les mots de passe côté client


132

Lorsque je souhaite mettre en place un système de connexion, je compare toujours le MD5 du mot de passe donné avec sa valeur dans le tableau des utilisateurs côté serveur.

Cependant, un de mes amis m'a dit qu'un mot de passe «clair» pouvait être reniflé par un logiciel réseau.

Ma question est donc la suivante: est-ce une bonne idée de hacher le mot de passe côté client? Vaut-il mieux que le hacher côté serveur?


1
Je pensais hacher le mot de passe côté client, mais seulement pour être sûr que le mot de passe du client n'existe jamais en texte clair côté serveur, ce qui signifie qu'ils peuvent se sentir plus faciles en sachant que je ne connais pas leur mot de passe réel, ou ne peut pas facilement y renoncer s'il est compromis. suis-je fou?
Cyclone

1
Juste pour être complet, puisque nous parlons de sécurité, et MD5 a été mentionné dans l'OP: il faut toujours utiliser un sel lors du cryptage d'un mot de passe. L'utilisation de MD5 simple et non salé est légèrement meilleure que de stocker des mots de passe en clair dans votre base de données.
sffc

1
@Cyclone Hashing UNIQUEMENT côté client est définitivement une mauvaise idée, car si l'attaquant connaît d'une manière ou d'une autre le hachage, il peut l'utiliser pour se connecter comme s'il connaissait le mot de passe, en contournant le code de hachage côté client.
Teejay

5
@Teejay: C'est pourquoi vous n'envoyez pas le hachage en clair. Le serveur envoie un sel aléatoire au client, vous ajoutez le hachage du mot de passe, et hachez le tout à nouveau, puis renvoyez-le au serveur qui fait le même calcul. Une attaque de relecture échoue car le sel sera différent
MSalters

2
Cette question ne devrait-elle pas être terminée sur security.stackexchange.com?
efr4k

Réponses:


115

En gros, votre ami a raison. Mais simplement hachant le mot de passe du côté client est seulement juste mieux que de le soumettre sous forme de texte au serveur. Quelqu'un, qui peut écouter vos mots de passe en texte brut, est certainement également capable d'écouter les mots de passe hachés et d'utiliser lui-même ces hachages capturés pour s'authentifier auprès de votre serveur.

Pour cette question, des protocoles d'authentification plus sécurisés sautent généralement à travers un certain nombre de cerceaux afin de s'assurer qu'une telle attaque de relecture ne peut pas fonctionner, généralement, en permettant au client de sélectionner un tas de bits aléatoires, qui sont hachés avec le mot de passe. , et également soumis en clair au serveur.

Sur le serveur:

  • générer quelques bits aléatoires
  • envoyer ces bits (en texte clair) au client

Sur le client:

  • générer quelques bits aléatoires
  • concaténer le mot de passe, les bits aléatoires du serveur et les bits aléatoires du client
  • générer le hachage de ce qui précède
  • soumettre des bits aléatoires (en texte clair) et du hachage au serveur

Comme le serveur connaît ses propres informations aléatoires ainsi que les bits aléatoires du client (il les a obtenus sous forme de texte clair), il peut effectuer essentiellement la même transformation. Ce protocole garantit que personne n'écoutant cette conversation ne pourra utiliser les informations ultérieurement pour s'authentifier à tort en utilisant les informations enregistrées (à moins qu'un algorithme très faible n'ait été utilisé ...), tant que les deux parties génèrent à chaque fois des "bits de bruit" différents, la poignée de main est effectuée.

Edit Tout cela est sujet aux erreurs et fastidieux et un peu difficile à obtenir (lire: sécurisé). Si possible, envisagez d'utiliser des implémentations de protocole d'authentification déjà écrites par des personnes bien informées (contrairement à moi! Ce qui précède n'est que de la mémoire d'un livre que j'ai lu il y a quelque temps.) Vous ne voulez vraiment pas écrire vous-même en général.


5
Comment peut-il s'authentifier avec le mot de passe haché dans le système de connexion puisqu'il sera à nouveau haché?
Zakaria

4
Si vous stockez vos mots de passe sous forme hachée sur le serveur (comme vous devriez), le client devra hacher le mot de passe deux fois: d'abord, le mot de passe seul, donc il correspond à la vue du serveur du monde, puis comme décrit ci-dessus pour l'intérêt du protocole.
Dirk

3
@Dirk, puisque l'attaquant peut renifler dans les deux sens, les "bits aléatoires" seraient reniflés. Ensuite, l'attaquant peut analyser (lire: force brute) la paire requête et réponse hors ligne pour trouver le mot de passe d'origine.
Pacerier

7
Cependant, dans le but de soumettre un mot de passe ou le hachage d'un mot de passe, souvent un processus asymétrique comme Diffie-Hellman est utilisé pour établir une clé de cryptage qui permet aux deux parties d'échanger des informations sans qu'une partie snooping ne puisse la décrypter. C'est exactement ce que fait SSL et c'est la raison pour laquelle la plupart des sites ont leur page de connexion sur HTTPS / SSL. SSL protège déjà contre les attaques de relecture. Je recommanderais d'utiliser SSL plutôt que de créer votre propre protocole. Bien que je sois d'accord avec le salage + le hachage du mot de passe côté client, mais envoyez-les via une connexion SSL établie.
AaronLS

14
Juste pour être clair: si vous n'utilisez pas HTTPS, peu importe le javascript que vous exécutez sur le client; un MITM serait capable de modifier le contenu de votre page avant qu'elle n'atteigne le client. HTTPS est la seule solution.
aidan

60

Tout d'abord, cela n'améliore PAS la sécurité de votre application (en supposant qu'il s'agisse d'une webapp).

Utilisez SSL (ou en fait TLS, qui est communément appelé SSL), ce n'est pas vraiment cher (mesurez le temps que vous utilisez pour trouver des moyens de le contourner et multipliez-le par le salaire minimum, l'achat d'un certificat gagne presque toujours).

Le pourquoi de cela est simple. TLS résout un problème (lorsqu'il est utilisé avec des certificats achetés et non auto-signés) qui est assez important en cryptographie: Comment savoir que le serveur auquel je parle est le serveur auquel je pense parler? Les certificats TLS sont une façon de dire: «Moi, l'autorité de certification, approuvée par votre navigateur, certifie que le site Web à [url] possède cette clé publique, avec une clé privée correspondante, que (clé privée) seul le serveur connaît, regarde J'ai signé ma signature sur tout le document, si quelqu'un l'a modifié, vous pouvez le voir ".

Sans TLS, tout cryptage devient inutile, car si je suis assis à côté de vous dans un café, je peux faire croire à votre ordinateur portable / smartphone que je suis le serveur et MiTM (Man in The Middle) vous. Avec TLS, votre ordinateur portable / smartphone criera "CONNEXION NON DE CONFIANCE", car je n'ai pas de certificat signé par une autorité de certification correspondant à votre site. (Cryptage vs Authentification).

Avis de non-responsabilité: les utilisateurs ont tendance à cliquer à droite sur ces avertissements: "Connexion non approuvée? Quoi? Je veux juste mes photos de chatons! Ajouter une exception Cliquez sur Confirmer Cliquez OUI! Chatons!"

Cependant, si vous ne voulez vraiment pas acheter de certificat, implémentez toujours le hachage javascript côté client (et utilisez la bibliothèque standford (SJCL) pour cela, NE JAMAIS IMPLÉMENTER CRYPTO YOURSELF ).

Pourquoi? Réutilisation du mot de passe! Je peux voler votre cookie de session (ce qui me permet de prétendre à votre serveur que je suis vous) sans HTTPS facilement (voir firesheep). Cependant si vous ajoutez un javascript à votre page de connexion qui, avant l'envoi, hache votre mot de passe (utilisez SHA256, ou mieux encore, utilisez SHA256, envoyez-leur une clé publique que vous avez générée puis cryptez le mot de passe haché avec cela, vous ne pouvez pas utiliser de salt avec ceci), puis envoie le mot de passe haché / chiffré au serveur. REHACHEZ le hachage sur votre serveur avec un sel et comparez-le à ce qui est stocké dans votre base de données (stockez le mot de passe comme ceci:

(SHA256(SHA256(password)+salt))

(enregistrez également le sel en texte brut dans la base de données)). Et envoyez votre mot de passe comme ceci:

RSA_With_Public_Key(SHA256(password))

et vérifiez votre mot de passe comme ceci:

if SHA256(RSA_With_Private_Key(SHA256(sent_password))+salt_for_username) == stored_pass: login = ok

Parce que, SI quelqu'un renifle votre client, il pourra se connecter en tant que client (piratage de session) mais il ne verra JAMAIS le mot de passe en clair (à moins qu'il ne modifie votre javascript, cependant, un pirate informatique de Starbucks ne saura probablement pas comment / être intéressé dans ce cas.) Ils auront donc accès à votre webapp, mais pas à leur email / facebook / etc. (pour lequel vos utilisateurs utiliseront probablement le même mot de passe). (L'adresse e-mail sera son nom de connexion ou sera trouvée dans son profil / paramètres sur votre application Web).


Je pense que c'est une bonne réponse mais elle a probablement besoin de plus d'informations sur la façon de saler correctement et qu'il vaut mieux utiliser une fonction de hachage "lente" avant de stocker le mot de passe sur le serveur (comme bcrypt).
Neyt

24

Vous êtes probablement d'accord pour ne pas vous en soucier - comme Dirk le mentionne même si vous hachez les mots de passe, un utilisateur malveillant pourrait être sur un réseau et voir le hachage être envoyé, et pourrait simplement envoyer le même hachage lui-même.

C'est légèrement mieux, en ce sens que cela empêche l'utilisateur malveillant de savoir quel est le mot de passe, mais comme ils peuvent toujours se connecter (ou potentiellement reconstruire le mot de passe d'origine ), ce n'est pas si utile.

En général, si vous êtes préoccupé par la sécurité des mots de passe et des données de vos utilisateurs (et vous devriez l'être!), Vous voudrez utiliser un serveur SSL sécurisé. Si cela ne vous préoccupe pas pour quelque raison que ce soit, vous pourriez aussi bien ne pas vous soucier du hachage; c'est juste la sécurité par l'obscurité .


Edit août 2014: Google insiste de plus en plus pour que les sites Web passent partout en HTTPS , car la sécurisation de la communication elle-même est le seul moyen d'empêcher les attaques de reniflement de réseau. Les tentatives d'obfusquer les données transmises ne feront qu'entraver, et non arrêter, un attaquant dédié, et peuvent donner aux développeurs un faux sentiment de sécurité dangereux.


Je pense que votre opinion selon laquelle le hachage client n'est que "légèrement meilleur" est vraie si vous vous concentrez uniquement sur l'obtention xdu mot de passe de l'utilisateur et l'accès à un service unique. Si vous considérez l'effet collectif, je dirais que c'est «beaucoup mieux»; car il empêche la création de grandes bases de données de recherche de mots de passe utilisées pour forcer les hachages salés par force brute sur plusieurs services. IMO. Découvrez ce que fait AWS Cognito dans le client pour référence.
f1lt3r

17

En fait, je ne suis pas d'accord pour dire que le hachage côté client est plus sécurisé dans ce cas. Je pense que c'est moins sûr.

L'intérêt de stocker un hachage du mot de passe dans votre base de données par opposition au mot de passe réel (ou même un mot de passe crypté) est qu'il est mathématiquement impossible d'obtenir le mot de passe d'origine à partir d'un hachage (bien qu'il soit théoriquement possible d'obtenir un entrée de hachage, dont la difficulté dépend de la force de sécurité de l'algorithme de hachage). Le vecteur d'attaque possible ici est que si un attaquant potentiel compromettait d'une manière ou d'une autre votre base de données de stockage de mots de passe, il ne serait toujours pas en mesure d'obtenir les mots de passe d'origine de vos utilisateurs.

Si votre mécanisme d'authentification envoie un hachage du mot de passe, alors dans ce scénario de faille de sécurité, l'attaquant n'a pas besoin de connaître le vrai mot de passe - il envoie simplement le hachage qu'il possède et hé hop, il a accès au compte d'un utilisateur particulier, et par extension, l'ensemble de votre système. Cela va complètement à l'encontre du point de stocker un mot de passe haché en premier lieu!

Le moyen le plus sûr de le faire est d'envoyer au client une clé publique à usage unique pour qu'il crypte le mot de passe, puis vous le décryptez et le hachez à nouveau côté serveur.

À propos, ce type de question obtiendra probablement des réponses plus d'experts sur Security StackExchange.


3
Tout à fait d'accord avec cela. Pour qu'une approche côté client fonctionne, il faudrait également envoyer le sel au client, ce qui invaliderait tout le but du salage!
James Wright

@JamesWright: Le point est d'envoyer un sel aléatoire pour chaque utilisation, ce qui empêche la réutilisation illégale des messages de connexion. (Une forme d'attaques de relecture). Envoyer le même sel à chaque fois est en effet inutile.
MSalters

Ce que vous devez faire est d'utiliser un "nonce" ( en.wikipedia.org/wiki/Cryptographic_nonce ). De cette façon, le serveur contrôle également le sel et le sécurise. Le hachage côté client est également important pour que le code JS injecté ne puisse pas le trouver facilement plus tard. Plus ici: stackoverflow.com/a/21716654/43615
Thomas Tempelmann

Pour utiliser salt + nonce dans un processus d'authentification de connexion, consultez cette réponse: stackoverflow.com/a/24978909/43615
Thomas Tempelmann

Évidemment, si vous le hachez du côté client, vous devrez le hacher à nouveau du côté serveur pour éviter le point que vous faites. Comme d'autres le soulignent cependant, pour la confidentialité, vous voulez déjà un cryptage côté client.
Daniel Methner

5

Notez que la protection des mots de passe contre des tiers n'est pas tout ce qu'il y a à faire.

Dès que la confidentialité est en jeu (et quand ce n'est pas le cas, de nos jours?), Vous ne voulez pas connaître le mot de passe. Vous ne pouvez pas abuser ou fuir ce que vous n'avez , si vous et vos clients peuvent mieux dormir si vous voyez jamais leurs mots de passe en texte clair.

Par conséquent, le hachage / chiffrement côté client a du sens.


D'accord! Beaucoup de gens passent à côté de ce point. Si je télécharge votre base de données de mots de passe de mots de passe hachés salés, et que je peux en craquer un seul en utilisant une base de données de recherche de hachage, il y a de fortes chances que je puisse tous les déchiffrer. Une fois que j'ai 50k mots de passe originaux, j'ai maintenant la clé des xutilisateurs sur les nservices qui ne chiffrent que sur le serveur. Si chaque service hache de manière unique le mot de passe avant de quitter le client, la grande base de données de mots de passe interservices devient beaucoup, beaucoup plus petite. Vérifiez votre trafic de connexion AWS, voyez ce qu'ils font. C'est probablement mon cher Watson.
f1lt3r


1

J'ai fait beaucoup de travail sur ce sujet récemment, IRL il y a deux problèmes avec le hachage côté client / le cryptage symétrique avec vraiment tuer l'idée: 1. Vous devez ramener le sel au serveur SOMEHOW ... et crypter côté client, vous auriez besoin d'un mot de passe ... ce qui va à l'encontre de l'objectif. 2. Vous exposez votre implémentation de hachage (ce n'est pas une affaire ÉNORME car la plupart des sites utilisent l'un des 3 ou 4 algos de hachage) ce qui facilite l'attaque (car il suffit d'en essayer un plutôt que n).

Ce que je suis finalement allé, c'était un cryptage asymétrique sur le client utilisant OpenPGP.js ou similaire ... Cela repose sur une clé importée ou générée côté client sur le client et le serveur envoyant sa clé publique. Seule la clé publique du client peut être renvoyée au serveur. Cela protège contre les attaques MIM et est aussi sécurisé que l'appareil (je stocke actuellement la clé privée du client par défaut dans localStore, c'est une démo).

L'avantage MAJEUR de ceci est que je n'ai jamais à avoir les données des utilisateurs stockées / même en mémoire non cryptées sur mon serveur / magasin de données (et la clé privée de mon serveur est physiquement séparée)

La base de cela était de fournir aux gens un moyen de communiquer en toute sécurité là où HTTPS était restreint (par exemple, Iran / Corée du Nord atc ...) et aussi juste une expérience amusante.

Je suis loin du premier à y penser, http://www.mailvelope.com/ utilise ceci


1

Si quelqu'un peut voir les données entrantes et sortantes sur votre connexion, l'authentification ne vous sauvera pas. Au lieu de cela, je ferais ce qui suit pour des trucs super secrets.

Les mots de passe sont préhachés côté client avant d'être envoyés au serveur. (Le serveur stocke une autre valeur hachée et salée de ce hachage envoyée depuis le navigateur).

Ainsi, une attaque d'intermédiaire pourrait leur permettre d'envoyer la même valeur hachée pour se connecter, mais le mot de passe de l'utilisateur ne serait pas connu. Cela les empêcherait d'essayer d'autres services avec les mêmes informations d'identification pour se connecter ailleurs.

Les données des utilisateurs sont également cryptées du côté du navigateur.

Ah, donc une attaque d'intermédiaire obtiendrait les données chiffrées, mais ne pourrait pas les déchiffrer sans le mot de passe réel utilisé pour se connecter. (mot de passe des utilisateurs stocké dans le DOM sur le navigateur lors de leur connexion). Ainsi, l'utilisateur réel verrait le contenu décrypté, mais pas l'intermédiaire. Cela signifie également qu'aucune NSA ou autre agence ne serait en mesure de vous demander / entreprise / fournisseur d'hébergement de déchiffrer ces données car il leur serait impossible de le faire également.

Quelques petits exemples de ces deux méthodes sont sur mon blog http://glynrob.com/javascript/client-side-hashing-and-encryption/


1

Récemment, GitHub et Twitter ont annoncé que les mots de passe étaient stockés dans des journaux internes. Cela s'est produit par inadvertance dans des rapports de bogues et d'autres journaux qui ont trouvé leur chemin dans splunk, etc. un gros problème car les administrateurs n'en auraient pas beaucoup besoin. Peu importe en tant qu'administrateurs, nous n'aimons pas voir les mots de passe.

La question est donc de savoir si le hachage doit avoir lieu côté client pour des raisons de sécurité, mais comment pouvons-nous protéger le mot de passe avant qu'il ne soit finalement haché et comparé par le côté serveur afin qu'il ne soit pas journalisé d'une manière ou d'une autre.

Le chiffrement n'est pas une mauvaise idée car les développeurs doivent au moins franchir des obstacles, et si vous constatez que les mots de passe sont entrés dans les journaux, vous pouvez simplement changer la clé de chiffrement, détruire l'original, et ces données deviennent inutiles. Mieux encore, faites tourner les touches tous les soirs et cela pourrait réduire considérablement les fenêtres.

Vous pouvez également hacher un hachage dans votre enregistrement d'utilisateur. Les mots de passe divulgués seraient des mots de passe en texte brut hachés. Le serveur stocke une version hachée du hachage. Bien sûr, le hachage devient le mot de passe, mais à moins que vous n'ayez une mémoire photographique, vous n'allez pas vous souvenir d'un 60 caractères bcyrpt. Sel avec le nom d'utilisateur. Si vous pouviez recueillir quelque chose sur l'utilisateur pendant le processus de connexion (sans exposer que l'enregistrement utilisateur existe), vous pouvez également ajouter un hachage plus robuste qui ne pourrait pas être partagé entre les sites. Aucun homme au milieu ne pourrait simplement couper et coller le hachage capturé entre les sites.

Combinez avec un cookie qui n'est pas renvoyé au serveur et vous pourriez être sur quelque chose. À la première demande, soumettez un cookie au client avec une clé, puis assurez-vous que le cookie ne retourne pas au service de connexion si peu de chances qu'il soit enregistré. Stockez la clé dans un magasin de session, puis supprimez-la juste après la connexion ou lorsque la session a expiré ... cela nécessite un état pour vous, les gars JWT, mais peut-être simplement utiliser un service nosql pour cela.

Donc, plus tard, un administrateur tombe sur l'un de ces mots de passe hachés et chiffrés dans splunk ou dans un outil de rapport de bogue. Cela devrait être inutile pour eux car ils ne peuvent plus trouver la clé de cryptage, et même s'ils l'ont fait, ils doivent alors forcer un hachage. De plus, l'utilisateur final n'a rien envoyé de texte en clair le long de la ligne, donc tout homme au milieu a au moins plus de difficulté et vous ne pouvez pas simplement accéder à un autre site et vous connecter.


Exactement ma préoccupation. Si le serveur se connecte par accident en raison d'une mauvaise mise en œuvre ou d'une intention malveillante, il est possible qu'un autre compte de l'utilisateur soit compromis s'il réutilise les mots de passe.
Dan

0

Considère ceci:-

Le client envoie une demande au serveur "J'ai un mot de passe à valider".

Le serveur envoie au client une chaîne aléatoire unique. R $

Le client intègre le mot de passe de l'utilisateur dans cette chaîne (en fonction des règles (variables) que vous souhaitez appliquer).

Le client envoie la chaîne au serveur et si le mot de passe est OK, le serveur connecte l'utilisateur.

Si le serveur reçoit une autre demande de connexion utilisant R $, l'utilisateur est déconnecté et le compte est gelé en attente d'enquête.

De toute évidence, toutes les autres mesures de sécurité (normales) seraient prises.


0

Cette idée de hachage côté client est de protéger l'utilisateur, pas votre site. Comme mentionné à plusieurs reprises déjà, le texte brut ou les mots de passe hachés ont tous deux accès à votre site de la même manière. Vous n'obtenez pas d'avantage de sécurité.

Mais le mot de passe réel et brut de vos utilisateurs ne doit être connu que par eux. Savoir ce qu'ils ont choisi comme mot de passe est une information qui peut être utilisée contre eux sur d'autres sites et systèmes. Vous êtes un site axé sur le client en le protégeant contre la découverte de son choix de mot de passe par vos développeurs de serveurs ou par des tiers.

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.