web-dev-qa-db-fra.com

Existe-t-il un moyen d'ajouter du hachage salé à mon authentification utilisateur sans casser mon ancien serveur de connexion

On me présente le scénario suivant:

J'ai une base de données MySQL avec une table d'utilisateurs. Le tableau comporte deux champs: username et password. Le mot de passe est stocké sous forme de hachage non salé.

Une application de plus de 15 ans utilise cette base de données pour authentifier l'accès à ses services. Il n'est accessible qu'en interne.

Notre équipe est chargée de moderniser ces services en proposant une nouvelle application en suivant les meilleures pratiques et les enseignements tirés des 15 dernières années (et potentiellement plus qui ont été ignorés dans l'application d'origine). Cette application est accessible à partir du large Internet ouvert.

Nous sommes censés réutiliser la base de données actuelle à des fins d'authentification pour permettre aux deux applications de s'exécuter en parallèle sur la même base de données d'authentification sous-jacente.

J'ai exprimé plusieurs préoccupations concernant la sécurité, car cette application concerne la gestion des données personnelles de mes collègues et de moi.

Nous avons décidé qu'une partie de notre modernisation est que des politiques de mot de passe sont mises en place et que les mots de passe sont stockés à la fois salés et poivrés.

Cela signifie que notre table de base de données obtiendrait un troisième champ salt et le champ password stocke maintenant notre hachage salé et poivré.

Le problème ici est que cela cassera l'authentification dans notre ancienne application. Comme le code est très ancien et que nous n'avons même plus de compilateur fonctionnel, il est hors de question de changer le code de l'application d'origine.

Ma question est donc:

  • Existe-t-il un moyen sûr d'ajouter du sel (et du poivre) à notre base de données d'authentification tout en conservant la capacité de l'ancienne application à authentifier les utilisateurs? Gardez à l'esprit que même si l'ancienne application n'est pas sécurisée par nature, elle ne sera pas accessible en dehors de notre intranet, mais la nouvelle application le sera.
30
Ben

Vous avez des exigences contradictoires ici. Les exigences de compatibilité vous obligent à conserver les anciens hachages. Les exigences de sécurité vous obligent à les supprimer. Vous devrez faire un choix ici sur les exigences à remplir.

Si vous décidez de conserver la compatibilité descendante, essayez de tirer le meilleur parti d'une mauvaise situation:

  • L'ancien hachage et le nouveau hachage doivent être stockés dans des tables différentes, et l'utilisateur de la base de données que l'application Web utilise ne doit pas avoir accès en lecture à l'ancien hachage. Utilisez des autorisations de table et/ou de colonne pour cela.
  • Dès que vous n'avez plus besoin de l'ancienne application, supprimez la table avec l'ancien hachage. Ashley Madison a échoué à ce stade - ils sont passés à bcrypt, puis pour une raison idiote, ils ont laissé les anciens hachages MD5 traîner dans la base de données. Lorsque la base de données a été divulguée, ce bcrypt fantaisie n'a pas beaucoup aidé ...

Ou, alternativement, si vous n'avez pas peur de créer un peu de gâchis:

  • Déposez les anciens hachages. Dans la nouvelle application, ajoutez l'option "Créer un mot de passe temporaire pour l'ancienne application". Il vous donne un mot de passe long et aléatoire qui est haché à l'ancienne et qui n'est conservé dans la base de données que pendant X minutes. L'utilisateur peut alors se connecter à l'ancienne application et le mot de passe est alors automatiquement supprimé.
50
Anders

Existe-t-il un moyen sûr d'ajouter du sel (et du poivre) à notre base de données d'authentification tout en conservant la capacité de l'ancienne application à authentifier les utilisateurs?

Oui, cela peut être fait. Vous trouverez ci-dessous des instructions de mise en œuvre de haut niveau. La technique de base consiste à hacher tous les mots de passe, puis à MITM la connexion entre le client et le serveur hérité afin de remplacer le mot de passe non haché par un mot de passe haché. Notez que vous devrez proposer un plan de déploiement; exécuter aveuglément l'étape 1 de la production va tout casser.

Étape 1: Salez tous les mots de passe existants, puis stockez le sel quelque part. Remplacez le champ de mot de passe de la base de données héritée par le mot de passe salé.

Étape 2: Créez une cale. Le shim acceptera des paramètres identiques à ceux des API héritées.
Donc, si l'API héritée est implémentée comme:

LegacyDoStuff(username,password,argument)
{
    if(!VerifyCredentials(username,password)) return AuthenticationError();
    result = DoStuff(argument);
    return result;
}

La nouvelle API est implémentée comme:

NewDoStuff(username,password,argument)
{
    hashedpassword = DoHash(password+getSalt(username))
    return LegacyDoStuff(username,hashedpassword,argument);
}

Étape 3: Pointez le client hérité sur le shim, au lieu du serveur principal (ou de manière équivalente, déplacez le serveur hérité vers le nouveau IP/DNS, puis placez le shim sur l'ancien IP/DNS).

Cette approche vous permet de traiter les éléments internes du code hérité comme une boîte noire, mais elle vous oblige à être conscient de la surface publique du code hérité, car votre cale devra envoyer des demandes/réponses entre le client et le serveur hérité.

Cette approche, contrairement aux approches décrites dans d'autres réponses, évite complètement de stocker l'ancien mot de passe. Cependant, cette approche est beaucoup plus difficile à faire et est beaucoup plus susceptible d'introduire des bogues.

24
Brian

Existe-t-il un moyen sécurisé d'ajouter du sel (et du poivre) à notre base de données d'authentification tout en conservant la capacité de l'ancienne application à authentifier les utilisateurs?

Non. La raison du salage et du hachage des mots de passe est que si la base de données utilisateur est piratée/divulguée/compromise, les mots de passe des utilisateurs ne sont pas accessibles à l'attaquant (voir Quel est l'intérêt du hachage des mots de passe? ). Dans la solution que vous décrivez, les mots de passe des utilisateurs sont toujours stockés dans la base de données des utilisateurs, dans une colonne adjacente, en texte clair. Cela va complètement à l'encontre de l'objectif de salage et de hachage des mots de passe.

11
mti2935

Il est clair que la table actuelle doit rester pour que l'ancienne application puisse fonctionner.

Ajoutez peut-être une nouvelle table avec des hachages salés + poivrés pour la nouvelle application à utiliser, puis:

  • Rendez l'ancienne table inaccessible à la nouvelle application!
  • Mettre à jour les deux tables lors de la mise à jour du mot de passe d'un utilisateur
  • Obliger tous les utilisateurs du nouveau système à mettre à jour/réinitialiser leur mot de passe
  • La nouvelle table peut stocker une copie de l'ancien hachage initialement, puis la mettre à jour pour être correctement hachée lorsque l'utilisateur met à jour son mot de passe.

Cela suppose que le système de contrôle des mots de passe est distinct de l'un ou l'autre des systèmes de contenu.

Cela signifie que toute vulnérabilité dans le nouveau système ne peut pas accéder aux anciens hachages (une fois migrés). La base de données pourrait avoir une vulnérabilité qui permet aux informations d'identification de la base de données du nouveau système d'avoir accès à une table, ce qu'elle ne devrait pas, mais c'est beaucoup moins probable que votre nouvelle application présente une vulnérabilité.

7
Douglas Leeder
  1. Ajoutez deux nouvelles colonnes, une colonne de sel et une nouvelle colonne de hachage, initialement nulle.
  2. Lorsqu'une demande d'authentification arrive, vérifiez le champ de sel.
  3. Si le champ a une valeur, il y a un hachage de nouveau style qui contient du poivre et du sel. Manipulez en conséquence.
  4. Sinon, il s'agit d'un hachage à l'ancienne. Vérifiez en utilisant l'ancien mécanisme. En supposant qu'il réussisse, vous avez maintenant le mot de passe en texte brut de la demande d'origine; générer et stocker un sel et vous avez maintenant tout le nécessaire pour calculer et stocker un hachage de nouveau style. Le système hérité ne saura rien de tout cela, donc seul le nouveau système peut le faire. (Il aurait été préférable qu'aucun des deux systèmes ne s'en occupe mais puisse déléguer le travail à la base de données elle-même. Le nouveau système le peut, l'ancien système ne le peut pas.)

Finalement, soit tout le monde s'est connecté au moins une fois et a eu ses hachages mis à jour de manière transparente (il n'y a plus de sels NULL dans le tableau), soit les seuls qui restent ne sont jamais connectés.

Mettre les hachages non salés et salés les uns à côté des autres dans le tableau illustre simplement le fait que tant que le système hérité continuera d'être utilisé, l'utilisation des meilleures pratiques dans le nouveau système restera non pertinente du point de vue de la sécurité .

5
Hayley

Oui, c'est possible.

Dans la nouvelle application, ayez un algorithme de hachage double de hachage de hachage, par exemple: étape 1: hachage du mot de passe salé, étape 2: hachage de ce hachage (pas de sel)

Approche n ° 1:

Développez une application autonome simple qui prend un mot de passe et génère le hachage salé d'un mot de passe utilisateur et s'affiche à l'écran ou en silence dans le presse-papiers.

Demandez à tous les utilisateurs internes de réinitialiser leur mot de passe dans l'ancienne application à la sortie de l'application autonome, et à partir de maintenant lors de la connexion, utilisez le processus de saisie du mot de passe dans l'application autonome pour générer le hachage du mot de passe qui sera entré dans la connexion écran. La sortie pourrait être générée dans le presse-papiers pour éviter les indices visuels.

Approche n ° 2

Si vous pouvez en quelque sorte utiliser la base de données, faites le hachage de hachage dans la base de données. Faites à l'étape 2 le hachage salé et ne le stockez que.

Modifier pour clarifier: exemple: si vous utilisez une base de données qui prend en charge des opérateurs personnalisés, déclarez un opérateur d'égalité personnalisé sur une colonne stockant le newsaltedhash (oldhash) en tant que type personnalisé. Lorsque l'application exécute une requête pour une ligne avec un nom d'utilisateur correspondant et oldhash, l'opérateur personnalisé exécutera newsaltedhash sur le hachage entrant et effectuera la comparaison. La réinitialisation du mot de passe est gérée par des déclencheurs d'insertion.

Résumé: Dans les deux scénarios, vos applications fonctionnent comme prévu à l'origine et le hachage de mot de passe stocké est un hachage double + sel. (Pepper ajouté en option dans l'une ou l'autre implémentation)

2
Frank

Cette réponse est inspirée par réponse de Brian et approche de Frank # 1 qui utilisent tous deux essentiellement le nouveau hachage salé comme mot de passe pour l'ancienne application. Étant donné que cela nécessite qu'une application récupère le sel de la base de données pour générer le hachage, il serait plus simple et plus sûr que cette application authentifie l'utilisateur et utilise un jeton aléatoire complètement séparé comme mot de passe pour l'ancien système.

Étape 1: choisissez une solution de hachage de mot de passe moderne

Choisissez une bibliothèque de hachage de mot de passe bien prise en charge pour la langue de votre choix, qui devrait gérer la génération de sel sécurisé pour vous. Il produira probablement une seule chaîne contenant le hachage, le sel et d'autres paramètres nécessaires pour vérifier le mot de passe, vous permettant de déployer progressivement un algorithme plus puissant à l'avenir. Par exemple, dans le cas de PHP, utilisez les fonctions de hachage de mot de passe intégrées .

Créez une nouvelle colonne dans la base de données pour stocker cette chaîne unique. Une façon de remplir cela initialement est de calculer NewHashFunction(OldStoredHash), puis d'exécuter NewVerifyFunction(NewStoredHash, OldHashFunction(UserEnteredPassword)). Il existe de nombreuses discussions à ce sujet, et cela ne fait aucune différence pour le reste de cette réponse.

Étape 2: videz l'ancienne colonne de mot de passe

Essuyez définitivement tous les anciens hachages non sécurisés, mais ne laissez pas tomber la colonne. À ce stade, personne ne peut se connecter à l'ancienne application, nous devons donc y remédier ...

Étape 3: Créez un outil pour vous connecter à l'ancienne application

Créez une page dans votre nouvelle application (où l'utilisateur est déjà authentifié) ou une page autonome (qui authentifie l'utilisateur à l'aide de la nouvelle bibliothèque de mots de passe) qui fait ce qui suit:

  • Génère un long mot de passe aléatoire
  • Stocke le hachage non salé de ce mot de passe aléatoire dans l'ancienne colonne de mot de passe pour l'utilisateur authentifié
  • Soit affiche le mot de passe à l'utilisateur pour entrer dans l'ancienne application, soit le soumet directement pour se connecter automatiquement à l'utilisateur

Notez que ce mot de passe aléatoire n'a pas besoin d'être stocké n'importe où, car si l'utilisateur veut se reconnecter, il peut simplement en générer un nouveau.

Étape 4: rendez-le plus sûr en expirant les jetons

Les mots de passe aléatoires sont forcément beaucoup plus forts que la plupart des utilisateurs ne l'auraient défini à moins d'utiliser un gestionnaire de mots de passe, mais ils seront toujours stockés non salés et probablement à l'aide d'un hachage rapide. Il existe également un risque que le mot de passe soit copié quelque part lorsqu'il est montré à l'utilisateur. Nous pouvons rendre les deux attaques beaucoup plus difficiles en n'ayant que les mots de passe aléatoires valides pour une courte période de temps.

Ajoutez une colonne supplémentaire à la base de données pour la "date d'expiration du mot de passe aléatoire". Cela peut être extrêmement court s'il se connecte automatiquement et quelques minutes si l'utilisateur doit saisir lui-même le mot de passe. Un travail planifié doit ensuite s'exécuter une fois par minute et effacer l'ancien champ de mot de passe pour toutes les lignes qui ont expiré.

1
IMSoP