如何在没有 HTTPS 的情况下使用 Javascript 通过 HTTP 安全地发送密码?
所有开发人员面临的非常基本的问题:每当用户提交表单时,密码都会通过网络发送,并且必须受到保护。我开发的网站没有 HTTPS。所有者既不想购买 SSL 证书,也对自签名证书不感兴趣。所以我想在提交表单时使用 Javascript 保护通过 HTTP 发送的密码。
这个其他问题没有给出任何明智的解决方案,我在另一个问题中情况。
如果我使用 MD5,就可以反转该密码字符串。随机数/HMAC 怎么样?有可用的 Javascript 库吗?或者你有什么建议/提示要解决吗?
The very basic issue all developers face: Whenever user submits the form, the password is sent via network and it must be protected. The site I develop for doesn't have HTTPS. Neither does the owner want to buy a SSL certificate, nor is he interested in a self-signed one. So I want to protect the password sent via HTTP using Javascript when submitting form.
This other question DOES NOT give any sensible solution and I am in another situation.
If I use MD5, one can reverse that password string. What about nonce/HMAC? Any available Javascript library for that? Or do you have any suggestion/hint to tackle?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
如果没有 SSL,则无法安全地发送用户可以验证的密码。
当然,您可以编写一些 JavaScript,通过散列或公钥加密来确保密码在网上传输时的安全。但是,用户如何确保 JavaScript 本身在到达他们之前没有被中间人篡改,将密码发送给攻击者而不是网站,甚至只是危及网站的安全性?算法?唯一的方法是让他们成为专家程序员,让他们在输入密码之前检查页面和脚本的每一行,以确保其正确无误。这不是一个现实的场景。
如果您希望密码免受中间人攻击,则必须购买 SSL 证书。没有其他办法。习惯它。
不……至少不简单。虽然 MD5 存在针对它的攻击,但它是一种哈希算法,因此是不可逆的。你将不得不暴力破解它。
但同样,中间人攻击者不需要查看您的 MD5。他可以简单地破坏您发送给用户的用于生成 MD5 的 JavaScript。
There is no way to send a password securely that the user can verify without SSL.
Sure, you can write some JavaScript that will make a password secure for over-the-wire transmission through hashing or public-key-encryption. But how can the user be sure that the JavaScript itself has not been tampered with by a man-in-the-middle before it reached them, to send the password to an attacker instead of the site, or even just compromise the security of the algorithm? The only way would be for them to be expert programmers and have them inspect every line of your page and script to ensure it was kosher before typing the password. That is not a realistic scenario.
If you want passwords to be safe from man-in-the-middle attacks, you must buy an SSL cert. There is no other way. Get used to it.
No... not trivially at least. Whilst MD5 has attacks against it, it's a hashing algorithm and thus unreversable. You would have to brute-force it.
But again, a man-in-the-middle attacker doesn't need to look at your MD5s. He can simply sabotage the JavaScript you send the user to make the MD5s.
这里的解决方案是根本不发送密码。使用挑战/响应。
在原始形式中包括一大块随机文本和一个密钥。根据服务器上的密钥将原始随机文本存储在会话中。当客户端提交表单时,使用JS将随机文本和密码哈希在一起。然后将用户名、密钥和散列随机文本发送到服务器。不要发送密码。在服务器上,使用密钥查找原始随机文本,与存储的密码执行相同的哈希操作。如果服务器哈希值与客户端哈希值匹配,那么您就知道客户端输入了正确的密码,而无需将密码发送到服务器。
无论密码是否正确,密钥和随机文本都会过期,因此它们都是一次性的。
The solution here is to not send the password at all. Use challenge/response.
In the original form include a large block of random text along with a key. Store the original random text in the session based on key on the server. When the client submits the form, use JS to hash the random text and password together. Then send the username, key, and hashed random text to the server. DO NOT send the password. On the server, use the key to lookup the original random text, perform the same hashing operation with the stored password. If the server-hashed value matches the client hashed value, then you know the client entered the right password without ever sending the password to the server.
Whether the password is right or not, expire the key and random text so each are one-time-use.
如果您真的想深入了解这一点,请查看 Diffie-Hellman 密钥交换 它的创建是为了“允许彼此事先不了解的两方通过不安全的通信通道共同建立共享密钥”,
但我不是密码学专家,所以我不完全知道是否如果攻击者同时拥有客户端(JavaScript 源代码)和传输机制(数据包嗅探器),那么它就非常安全
If you REALLY want to deep-dive into this, look at the Diffie-Hellman key exchange which was created to "allow two parties that have no prior knowledge of each other to jointly establish a shared secret key over an insecure communications channel"
I'm not a cryptography expert though, so I don't fully know if it's really secure if an attacker has both the Client (JavaScript source code) and the transport mechanism (Packet sniffer)
您可以在发送之前使用 javascript RSA 实现对密码进行加密。 (这是 Javascript 中的 RSA 的示例。)
但我相信这个和使用哈希函数都将是容易受到重放攻击。所以,要小心。
You can use a javascript RSA implementation to encrypt the password before sending. (Here is an example of RSA In Javascript.)
But I believe both this one and using a hash function will be vulnerable to replay attacks. So, be careful.
不幸的是,无法确保非加密请求的安全性。任何有权访问您的 javascript 的人都可以对其进行反向工程/篡改,并且任何拥有数据包嗅探器的人都将能够观看未加密的流量。这两个事实一起意味着:
没有 SSL?没有安全保障。
Unfortunately there will be no way to ensure security of a non-encrypted request. Anyone with access to your javascript will simply be able to reverse engineer it/tamper with it and anyone with a packet sniffer will be able to watch the unencrypted traffic. These two facts together mean:
No SSL? No security.
您拥有的任何传输都将是透明的;也就是说,如果没有 SSL,您的关键信息将会暴露。值得与网站所有者讨论这一点。换句话说,最好采取必要的措施来强化您的数据传输,而 SSL 是您可以采取的基本、廉价的步骤之一。
Any transmission that you have will be in the clear; that is, without SSL your critical information will be exposed. It is worth discussing that point with the site Owner. In other words, it's best to take necessary measure to fortify your data transmission, and SSL is one the basic, cheap steps you can take.
我认为这里的问题不是技术,而是你如何解释SSL的重要性。为他们提供可靠的阅读材料,我相信网上有很多。
i don't think the issue here is the technology, but how you explain the importance of SSL. Provide them with reliable reading materials, i'm sure there are plenty over the web.
该解决方案要求客户端能够使用仅客户端和服务器已知的秘密加密密钥来加密密码。
SSL 通过要求服务器和客户端 Web 浏览器拥有自己的非对称公钥/私钥对来实现此目的,它们使用该密钥对在它们之间加密和传输随机会话密钥。然后,对话的其余部分将使用该安全会话密钥。
因此,您会问如何解决与 SSL 相同的问题,而无需拥有仅客户端和服务器知道的密钥。我不是专家,但看起来这是不可能做到的,或者至少不容易做到。
The solution requires the client to be able to encrypt the password using a secret encryption key known only to the client and the server.
SSL accomplishes this by requiring both the server and the client web browser to have their own asymmetric public/private keypair, which they use to encrypt and transmit a random session key between them. The rest of the conversation then uses that secure session key.
So you're asking how to solve the same problem as SSL without the benefit of having a secret key that is known only to the client and server. I'm no expert, but it looks like this can't be done, or at least not easily.
如果您无法访问 SSL,MD5 应该足以防止意外发现密码(例如在网络日志文件或其他文件中)。任何其他事情都会浪费时间。只需确保该应用程序不会允许访问敏感信息(即信用卡号、病史等)。
正如其他评论者所建议的那样,严重的攻击者将能够破坏页面上任何类型的安全性。即使 SSL 也是一个小障碍,因为大多数用户使用易于猜测的密码,在任何地方重复使用相同的密码,将他们的密码提供给任何询问的人,或者可能被复制的页面或“技术”欺骗而放弃他们的密码。支持”电话。
If you don't have access to SSL, MD5 should be adequate to prevent accidental discovery of passwords (such as in a network log file or something). Anything else would be a waste of time. Just make sure the app doesn't give access to sensitive information (ie, credit card numbers, medical history, etc).
Like others commenters have suggested, a serious attacker will be able to break any type of security on the page. Even SSL is a small barrier since most users use easy-to-guess passwords, re-use the same passwords everywhere, will give their password to anybody that asks, or can be tricked into giving up their password by a copied page or "tech support" phone call.
- 英语 -
我在想一些事情,但我不知道它是否真的安全。如果您可以将表单放入 php 文件中,那么您可以创建一个算法来创建基于时间或其他内容的字符串,然后将该字符串放入 html 中。
当用户在密码输入字段中输入密码时,调试时看不到用户输入的值,因此在通过 post 或 get 发送信息之前,可以使用密码 user 作为提示,预先对加密字符串进行加密生成,然后发送它并插入用户输入的密码。
这样,攻击者就无法掌握所有 js 代码,因此他们需要发现您创建的算法来解密它。
这只是一个想法,所以如果您能告诉我这为什么不安全,我将不胜感激。
- 西班牙语 -
Se me acaba de ocurrir algo que puede servir, pero no se si realmente sea algo seguro.在 php 中,使用通用算法将 Cree 和字符串作为基本时间戳或其他算法,并在 html 中使用 cadena 的颜色。
请注意,如果您在密码中输入密码,请在调试时使用 puede ver el valor que tecleo el usuario (no se si exita manera pero no quiseinvestigar más), asi que podemos utilizar la contraseña que el usuario escribió Como palabra clave para encriptar la cadena de texto que previamente habiamos Generado con php, por medio de un algoritmo en JS. Sería algo así como encriptar lo encriptado。后面的事情不会发生,也不会发生最后的结果。
Buscando un contra, lo único que se me ocurra es que el atacante tentrá que dedicarle mucho tiempo para tratar de encontrar el agoritmo que Creamos por medio de php y poder decriptar la cadena Final, o tentrá que hackear el servidor para acceder al php y obtener埃尔阿尔戈里特莫。
这就是我的想法,因为我的想法是我的,我的想法是不安全的,我的想法是这样的。
-- English --
i think in something, but i don't know if it could be really secure. If you can put your form in a php file, then you can create an algoritm for create a string based in time or in something else, and then put this string in your html.
When the user type a password in a password input field, when you debug it you canot see the value typed by user, so before send the information via post or get, you can use the password user as a hint to encrypt the encrypted string previosly generated, and then, just sent it insted of the password typed by user.
In this way, the attackers dont have all inside the js code, so they will need discover the algoritm that you create to decrypt it.
This is just an idea, so if you can tell me how this can not be safe, I would appreciate it.
-- Spanish --
Se me acaba de ocurrir algo que puede servir, pero no se si realmente sea algo seguro. Por medio de php puedes generar un algoritmo que cree un string en base al timestamp o algo más, y después colocar esta cadena en el html.
Note que cuando alguien escribe una contraseña en un campo input tipo password, con un debug no se puede ver el valor que tecleo el usuario (no se si exista manera pero no quise investigar más), asi que podemos utilizar la contraseña que el usuario escribió como palabra clave para encriptar la cadena de texto que previamente habiamos generado con php, por medio de un algoritmo en JS. Sería algo así como encriptar lo encriptado. Posteriormente lo que estariamos enviado no sería la contraseña tecleada, si no esta última cadena resultante.
Buscando un contra, lo único que se me ocurra es que el atacante tendrá que dedicarle mucho tiempo para tratar de encontrar el agoritmo que creamos por medio de php y poder decriptar la cadena final, o tendrá que hackear el servidor para acceder al php y obtener el algoritmo.
Esto es solo una idea, por lo que si pueden decirme como esto puede no ser seguro, se los agradecería.
如前所述,所有这些都无法防止服务器欺骗,因为这需要信任客户端 Javascript 的能力。但是,如果我们确定服务器不会被欺骗(签名证书、哈希签名不受长度扩展等影响),但不能连接不会受到窃听者的攻击,那么我的方法如下: d 实施它。
我认为最安全的方法是,不存储 H(密码),其中 H 是您选择的哈希函数,而是存储 g^H(密码),即使用密码作为 Diffie-Hellman 密钥交换的私钥。 (您也应该为不同的用户使用随机 g - 它成为您的盐。)然后为了验证,您生成一个随机数 b,发送用户 g^b,并计算 (g^H(password ))^b。用户不需要知道 g——他们只需要计算 (g^b)^H(密码) = (g^H(密码))^b。现在你有了一个双方都知道的数字iff用户输入了正确的密码,并且基于知道正确的数字构建质询-响应零知识证明是微不足道的,而使用随机数作为服务器的“私钥”使该方法免受重放攻击。
As mentioned, none of this is secure against server spoofing, as that requires an ability to trust the client-side Javascript. But if we're sure that the server can't be spoofed (signed cert, hash signing immune to length-extension, etc.) but not that the connection is immune to eavesdroppers, here's how I'd implement it.
I think the most secure way is, instead of storing H(password), where H is your hash function of choice, store g^H(password) i.e. use the password as the private key for Diffie-Hellman key exchange. (You should also probably use a random g for different users, too--it becomes your salt.) Then to verify, you generate a nonce b, send the user g^b, and compute (g^H(password))^b. The user does not need to know g--they need only compute (g^b)^H(password) = (g^H(password))^b. Now you have a number that both parties know iff the user entered the right password, and constructing a challenge-response zero-knowledge proof based on knowing the correct number is trivial, while the random number used as the server's "private key" makes the approach immune to replay attacks.