Disons que mon mot de passe est abc
. Je veux l'envoyer au serveur via HTTP.
Je pourrais l'envoyer en texte clair et laisser le serveur le hacher et le comparer aux entrées de sa base de données, mais alors toute personne qui peut voir le trafic via cette connexion verrait le mot de passe en texte clair.
Ainsi, je pourrais le hacher côté client et laisser le serveur le comparer sans le hacher car il est déjà haché (ou le serveur pourrait même doubler le hachage, mais aucune différence dans cette situation). Mais là encore, toute personne qui peut voir le trafic verra le mot de passe haché, puis enverra le mot de passe haché au serveur et le serveur l'acceptera.
Comment envoyer des mots de passe via HTTP? Dois-je implémenter un algorithme de chiffrement comme le chiffrement à clé publique RSA? Ou est-ce impossible?
La méthode doit être utilisable dans n'importe quel navigateur.
Tu ne peux pas.
Pour envoyer des informations en toute sécurité sur un canal non sécurisé, vous avez besoin d'un chiffrement.
Le chiffrement symétrique est désactivé, car vous devez d'abord transporter la clé, ce que vous ne pouvez pas faire en toute sécurité sur un canal non sécurisé [*].
Cela vous laisse avec la cryptographie à clé publique. Vous pouvez bien sûr lancer le vôtre , mais vous ne voulez pas être un Dave , donc c'est fini, ce qui vous laisse avec HTTPS.
[*] Vous pouvez bien sûr essayer d'utiliser un canal sécurisé pour échanger la clé, par exemple l'échange physique d'une clé. Ensuite, vous pouvez utiliser la cryptographie à clé secrète, comme Kerberos.
TLS est vraiment le seul moyen de le faire.
Mais que se passe-t-il si je le crypte avec JavaScript?
L'attaquant peut modifier le JavaScript que vous envoyez au client, ou simplement injecter son propre JavaScript qui enregistre toutes les informations saisies.
Ensuite, j'utiliserai CSP et SRI pour empêcher l'ajout de scripts et la modification de mes propres scripts.
Heureux que vous utilisiez des outils modernes pour protéger votre site, mais le SRI dans un contexte non sécurisé ne protège vraiment que contre la compromission d'une ressource externe. Un attaquant peut simplement modifier les en-têtes CSP et les tags SRI.
Il n'y a vraiment aucun moyen de le faire sans utiliser le chiffrement depuis le début, et la seule façon standard de le faire est d'utiliser TLS.
Bien que je convienne que vous devez utiliser HTTPS, vous pouvez le rendre encore plus sécurisé en utilisant le mécanisme d'authentification de réponse au défi salé (SCRAM, voir RFC 5802 ) pour l'échange d'authentification réel.
Ce n'est pas trivial à implémenter, mais l'essentiel est que, plutôt que d'envoyer le mot de passe au serveur, vous envoyez au serveur la preuve que vous connaissez le mot de passe. Étant donné que dériver la preuve utilise un nonce du client et du serveur, ce n'est pas quelque chose qui peut être réutilisé par un attaquant (comme l'envoi du hachage lui-même).
Cela a quelques avantages supplémentaires à utiliser HTTPS avec l'authentification de base que vous décrivez:
Veuillez noter que ce n'est sécurisé que si le client est capable d'effectuer les calculs SCRAM sans téléchargement de code depuis le serveur . Vous pouvez fournir un gros client ou les utilisateurs peuvent écrire leur propre code qu'ils contrôlent. Le téléchargement du code SCRAM sur HTTP donnerait à un attaquant la possibilité de modifier le code SCRAM pour envoyer le mot de passe en texte clair, ou autrement l'exposer.
Vous devez certainement déployer TLS dans ce cas.
Si vous décidez d'essayer d'inventer un système de sécurité de transport sur HTTP, vous allez finalement finir par implémenter un sous-ensemble de la fonctionnalité TLS. Il existe de nombreux pièges à prendre en compte lors de la conception et de la mise en œuvre d'un tel système, qui sont encore amplifiés lorsque vous choisissez d'essayer de mettre en œuvre le système avec un langage qui n'offre pas de nombreuses fonctionnalités de sécurité.
Même si vous avez implémenté une implémentation correcte d'un protocole cryptographique en JavaScript (ce qui est déjà un gros défi), vous ne pouvez pas vous fier à cette implémentation qui résiste aux attaques temporelles, et le tout se brise si quelqu'un a des scripts désactivés (par exemple avec NoScript ).
En règle générale, vous devez choisir l'implémentation qui comprend les composants de confiance les plus simples, bien compris et qui nécessitent que vous écriviez le moins de code critique pour la sécurité. Pour citer Andrew Tannenbaum:
Un nombre important de problèmes (dans la sécurité des applications) sont causés par des logiciels bogués, ce qui se produit parce que les fournisseurs ajoutent de plus en plus de fonctionnalités à leurs programmes, ce qui signifie inévitablement plus de code et donc plus de bogues.
Dois-je implémenter un algorithme de chiffrement comme le chiffrement à clé publique RSA?
Si vous envisagez d'essayer cela, vous pouvez tout aussi bien faire le plein kilomètre et utiliser HTTPS. Puisque vous ne semblez pas être un expert, le "chiffrement de votre propre" chiffrement aura sans aucun doute des erreurs de mise en œuvre qui le rendront peu sûr.
C'est en fait tout à fait possible.
Le mot de passe doit être haché côté client, mais pas avec une fonction statique. La méthode suivante utilise deux étapes et s'inspire de authentification d'accès Digest :
REMARQUE: Le serveur conserve un HMAC du mot de passe et la clé correspondante ( Résumé );
Cela vous protège contre la relecture.
L'intérêt principal que je vois n'est pas une protection contre les écoutes, mais pour être complètement sûr que le mot de passe en clair ne sera pas stocké sur le serveur, pas même dans un journal système (voir Twitter ou GitHub ).
Remarque: HMAC peut être remplacé par PBKDF2.
Il existe en fait un moyen d'authentifier un utilisateur via une connexion non sécurisée: protocole Secure Remote Password (SRP) . SRP est spécifiquement conçu pour permettre à un client de s'authentifier auprès d'un serveur sans qu'un attaquant Man-in-the-Middle puisse capturer le mot de passe du client, ou même rejouer l'authentification pour usurper l'identité du client ultérieurement, que l'authentification ait réussi ou non. De plus, une authentification réussie avec SRP crée une clé secrète partagée que le client et le serveur connaissent, mais pas un MitM. Cette clé secrète pourrait être utilisée pour le chiffrement symétrique et/ou les HMAC.
Cependant, il existe un certain nombre de limitations de SRP:
En d'autres termes, alors que SRP peut être utile dans les situations où vous avez un client de confiance qui n'a pas besoin de télécharger son code via la connexion non sécurisée et vous avez également un autre moyen sécurisé d'enregistrer les utilisateurs, SRP ne convient pas pour une application web. Les applications Web téléchargent toujours leur code à partir du serveur, donc si la connexion au serveur n'est pas sécurisée, un MitM (ou un autre attaquant du réseau, par exemple quelqu'un usurpant le DNS) peut injecter du code malveillant dans l'application Web et il n'y a rien que vous, la victime peut y remédier. Une fois que ce code est là, il peut capturer n'importe quel mot de passe ou d'autres données que vous entrez, voler toute clé générée et altérer toutes les demandes que vous envoyez ou les réponses que vous recevez à votre insu.
Il est certainement possible d'envoyer un mot de passe en toute sécurité en utilisant HTTP. Il y a même une norme pour cela. C'est appelé HTTP-Digest
et il est défini dans la RFC 7616. Il fait partie de la spécification HTTP depuis un certain temps. Il a été initialement conçu pour utiliser uniquement l'algorithme de résumé de message MD5 ("hachage"), mais des révisions ultérieures de la norme permettent au client et au serveur de négocier l'algorithme à utiliser.
Malheureusement, il existe de nombreux problèmes avec HTTP-digest et le plus flagrant d'entre eux est que le serveur doit avoir le mot de passe en texte clair. Ainsi, bien qu'il soit possible de communiquer des mots de passe en toute sécurité à l'aide de HTTP, il n'est pas possible de stocker en toute sécurité des mots de passe sur le serveur pendant son utilisation. Donc, fondamentalement, ce n'est pas utile.
Comme d'autres l'ont dit, il serait préférable d'implémenter TLS car il résout plusieurs problèmes en même temps et il est assez compatible avec le futur.
Comme d'autres l'ont dit TLS! TLS! TLS! (et avec une longueur de clé décente aussi)
Mais si vous devez utiliser HTTP et tout serveur à implémenter, est-ce à usage programmatique ou humain? Si vous êtes à usage humain, envisagez-vous l'authentification de base ou basée sur un formulaire? Et vos utilisations sont-elles capables d'appliquer un peu de logique, par exemple. pas pour joe public à utiliser. Faut-il protéger autre chose, ou simplement le mot de passe lui-même?
Si oui, vous pourrez peut-être regarder:
Cependant, avec TLS, les certificats sont bon marché (même gratuits) de nos jours, donc les systèmes d'obscurcissement alambiqués n'ont vraiment plus de raison d'exister.