web-dev-qa-db-fra.com

Comment envoyer un mot de passe en toute sécurité via HTTP?

Si, sur un écran de connexion, l'utilisateur envoie un formulaire avec son nom d'utilisateur et son mot de passe, le mot de passe est envoyé en texte brut (même avec POST, corrigez-moi si je me trompe).

La question est donc de savoir quel est le bon moyen de protéger l’utilisateur et son mot de passe contre le tiers susceptible d’écouter les données de la communication.

Je suis conscient que HTTPS est une solution au problème, mais existe-t-il un moyen de garantir au moins un certain niveau de sécurité à l'aide du protocole HTTP standard (demande POST)? (peut-être en utilisant javascript d'une certaine manière)

EDIT J'ai peut-être oublié certaines choses importantes.

J'étais sur une page - PHP page de connexion générée, qui est bien sûr envoyée à l'utilisateur dans une requête HTTP GET sous forme de fichier HTML. Aucune connexion (@Jeremy Powel) n'a été établie. entre le serveur et le client, je ne peux donc pas créer un tel protocole de liaison et je souhaite que le processus complet soit transparent pour l'utilisateur: il souhaite soumettre un mot de passe et non pas traiter avec la cryptographie.

Merci.

110
Kornelije Petak

L'utilisation de HTTP avec SSL vous facilitera grandement la vie et vous pourrez vous reposer à l'aise. Des personnes très intelligentes (au moins plus intelligentes que moi!) Ont scruté cette méthode de communication confidentielle pendant des années.

61
Jeremy Powell

L'authentification sécurisée est un sujet vaste. En bref, comme @ jeremy-powell l'a mentionné, privilégiez toujours l'envoi d'informations d'identification par HTTPS plutôt que par HTTP. Cela éliminera beaucoup de maux de tête liés à la sécurité.

Les certificats TSL/SSL sont assez bon marché ces jours-ci. En fait, si vous ne voulez pas du tout dépenser d’argent, il existe une autorité de certification gratuite letsencrypt.org - automatisée.

Vous pouvez aller plus loin et utiliser caddyserver.com , qui appelle letencrypt en arrière-plan.

Maintenant, une fois que nous avons eu le protocole HTTPS hors du chemin ...

Vous ne devez pas envoyer votre identifiant et votre mot de passe via les paramètres POST charge utile ou GET). Utilisez plutôt un en-tête Authorization (schéma d’authentification d’accès de base), qui est construit comme suit:

  • Le nom d'utilisateur et le mot de passe sont combinés en une chaîne séparée par deux points, par exemple: nom d'utilisateur: mot de passe
  • La chaîne résultante est codée à l'aide de la variante RFC2045-MIME de Base64, sauf qu'elle ne se limite pas à 76 caractères/ligne.
  • La méthode d’autorisation et un espace, c’est-à-dire "Basic", sont ensuite placés avant la chaîne codée.

source: Wikipedia: en-tête d'autorisation

Cela peut sembler un peu compliqué, mais ce n’est pas le cas. Il existe de nombreuses bibliothèques de qualité qui vous fourniront cette fonctionnalité immédiatement.

Il y a quelques bonnes raisons d'utiliser un en-tête d'autorisation

  1. C'est un standard
  2. C'est simple (après avoir appris à les utiliser)
  3. Cela vous permettra de vous connecter au niveau de l'URL, comme ceci: https://user:[email protected]/login _ (Chrome, par exemple, le convertira automatiquement en en-tête Authorization)

IMPORTANT:
Comme l'a souligné @zaph dans son commentaire ci-dessous, l'envoi d'informations confidentielles sous forme de requête GET n'est pas une bonne idée, car cela finira probablement dans les journaux du serveur.

enter image description here

29
FullStackForger

Vous pouvez utiliser un schéma de réponse par défi. Dites que le client et le serveur connaissent tous deux un secret S. Ensuite, le serveur peut être sûr que le client connaît le mot de passe (sans le révéler) en:

  1. Le serveur envoie un nombre aléatoire, R, au client.
  2. Le client envoie H (R, S) au serveur (où H est une fonction de hachage cryptographique, telle que SHA-256)
  3. Le serveur calcule H (R, S) et le compare à la réponse du client. S'ils correspondent, le serveur sait que le client connaît le mot de passe.

Edit:

Il y a un problème ici avec la fraîcheur de R et le fait que HTTP est sans état. Cela peut être géré en demandant au serveur de créer un secret, appelez-le Q, que seul le serveur connaît . Ensuite, le protocole va comme ceci:

  1. Le serveur génère un nombre aléatoire R. Il envoie ensuite au client H (R, Q) (qui ne peut être falsifié par le client).
  2. Le client envoie R, H (R, Q) et calcule H (R, S) et le renvoie au serveur (où H est une fonction de hachage cryptographique, comme SHA-256).
  3. Le serveur calcule H (R, S) et le compare à la réponse du client. Ensuite, il faut R et calcule (encore) H (R, Q). Si la version du client de H (R, Q) et H (R, S) correspond au nouveau calcul du serveur, celui-ci considère que le client est authentifié.

A noter que H (R, Q) ne pouvant pas être falsifié par le client, H (R, Q) agit en tant que cookie (et pourrait donc être implémenté en tant que cookie).

n autre Edit:

L'édition précédente du protocole est incorrecte, car quiconque a observé H (R, Q) semble être capable de le rejouer avec le hachage correct. Le serveur doit se rappeler quels R ne sont plus frais. Je réponds à cette question pour que vous puissiez éditer tout ça et trouver quelque chose de bien.

14
Jeremy Powell

Si votre hébergeur le permet ou si vous devez gérer des données sensibles, utilisez HTTPS, point à la ligne. (C'est souvent requis par la loi).

Sinon, si vous voulez faire quelque chose sur HTTP. Je ferais quelque chose comme ça.

  1. Le serveur intègre sa clé publique dans la page de connexion.
  2. Le client remplit le formulaire de connexion et clique sur Soumettre.
  3. Une demande AJAX obtient l'horodatage actuel du serveur.
  4. Le script côté client concatène les informations d'identification, l'horodatage et un sel (haché à partir de données analogiques, par exemple les mouvements de la souris, les événements liés aux touches), le chiffre en utilisant la clé publique.
  5. Soumet le hachage résultant.
  6. Le serveur déchiffre le hachage
  7. Vérifie si l'horodatage est suffisamment récent (autorise uniquement une courte fenêtre de 5 à 10 secondes). Rejette la connexion si l'horodatage est trop ancien.
  8. Stocke le hachage pendant 20 secondes. Rejette le même hachage pour la connexion pendant cet intervalle.
  9. Authentifie l'utilisateur.

Ainsi, le mot de passe est protégé et le même hachage d’authentification ne peut pas être lu.

A propos de la sécurité du jeton de session. C'est un peu plus difficile. Mais il est possible de rendre un peu plus difficile la réutilisation d'un jeton de session volé.

  1. Le serveur définit un cookie de session supplémentaire contenant une chaîne aléatoire.
  2. Le navigateur renvoie ce cookie à la prochaine demande.
  3. Le serveur vérifie la valeur dans le cookie. S'il est différent, il détruit la session, sinon tout va bien.
  4. Le serveur définit à nouveau le cookie avec un texte différent.

Ainsi, si le jeton de session a été volé et qu'une demande est envoyée par quelqu'un d'autre, la session sera détruite à la demande suivante de l'utilisateur d'origine. Donc, si l'utilisateur navigue activement sur le site, en cliquant souvent sur des liens, le voleur n'ira pas loin avec le jeton volé. Ce schéma peut être renforcé en exigeant une autre authentification pour les opérations sensibles (comme la suppression de compte).

EDIT: Veuillez noter que cela n’empêche pas les attaques MITM si l’attaquant configure sa propre page avec une clé publique différente et des demandes de proxy au serveur. Pour se protéger contre cela, la clé publique doit être épinglée dans la mémoire de stockage locale du navigateur ou dans l'application pour détecter ce type de trucs.

A propos de l'implémentation: RSA est probablement l'algorithme le plus connu, mais il est assez lent pour les longues clés. Je ne sais pas à quelle vitesse une implémentation de PHP ou Javascript) serait. Mais il existe probablement des algorithmes plus rapides.

10
Calmarius

J'utiliserais un système d'échange de clés Diffie-Hellman côté serveur et côté client avec AJAX ou plusieurs formulaires soumis (je recommande l'ancien), bien que je ne voie pas de bonne mise en œuvre de ceux-ci sur Internet. Rappelez-vous qu’une bibliothèque JS peut toujours être corrompue ou modifiée par MITM et que le stockage local peut être utilisé dans une certaine mesure.

4
Andrey Akhmetov

Vous pouvez utiliser SRP pour utiliser des mots de passe sécurisés sur un canal non sécurisé. L'avantage est que même si un attaquant détecte le trafic ou compromet le serveur, il ne peut pas utiliser les mots de passe d'un autre serveur. https://github.com/alax/jsrp est une bibliothèque javascript qui prend en charge les mots de passe sécurisés via HTTP dans le navigateur ou côté serveur (via un nœud).

3
Brian Minton

HTTPS est si puissant parce qu'il utilise une cryptographie asymétrique. Ce type de cryptographie vous permet non seulement de créer un tunnel crypté, mais vous pouvez également vérifier que vous parlez à la bonne personne, et non à un pirate informatique.

Voici le code source Java qui utilise le chiffrement asymétrique RSA (utilisé par PGP) pour communiquer: http://www.hushmail.com/services/downloads/

1
rook

vous pouvez utiliser ssl pour votre hôte il y a un projet gratuit pour ssl comme letsencrypt https://letsencrypt.org/

0
mk990