如何通过HTTP安全地发送密码?

时间:2009-10-17 18:32:49

标签: security http encryption passwords plaintext

如果在登录屏幕上用户使用他的用户名和密码提交表单,则密码将以纯文本形式发送(即使使用POST,如果我错了也请更正)。

所以问题是保护用户及其密码的正确方法是针对可能正在窃听通信数据的第三方?

我知道HTTPS是解决问题的方法,但有没有办法确保使用标准HTTP协议(POST请求)至少达到一定程度的安全性? (也许以某种方式使用javascript)

修改 我可能遗漏了一些重要的事情。

我的目标是一个页面 - 这是PHP生成的登录页面,当然,它作为HTML文件在HTTP GET请求中发送给用户。服务器和客户端之间没有建立(@Jeremy Powel)连接,所以我无法创建这样的握手协议。我希望整个过程对用户透明 - 他想提交密码,而不是处理加密。

感谢。

9 个答案:

答案 0 :(得分:60)

使用HTTP和SSL将让您的生活更轻松,您可以放松身心非常聪明的人(至少比我聪明!)多年来仔细审查了这种保密通信方式。

答案 1 :(得分:27)

安全身份验证是一个广泛的主题。简而言之,正如@ jeremy-powell所提到的,总是倾向于通过HTTPS而不是HTTP发送凭据。它会消除许多与安全相关的麻烦。

TSL / SSL证书如今非常便宜。事实上,如果你根本不想花钱,那就有免费的 letsencrypt.org - 自动证书管理局。

您可以更进一步,使用 caddyserver.com 在后台调用letsencrypt。

现在,一旦我们将HTTPS取消了......

您不应通过POST有效内容或GET参数发送登录名和密码。请改用Authorization标头(基本访问认证方案),其构造如下:

  
      
  • 用户名和密码组合成一个由a分隔的字符串   冒号,例如:用户名:密码
  •   
  • 生成的字符串使用编码   Base64的RFC2045-MIME变体,但不限于76   字符/行。
  •   
  • 然后是授权方法和空格,即“基本”   放在编码字符串之前。
  •   
     

来源:Wikipedia: Authorization header

看起来有点复杂,但事实并非如此。 有很多好的库可以为您提供开箱即用的功能。

使用Authorization标头有几个很好的理由

  1. 这是一个标准
  2. 这很简单(在您学习如何使用它们之后)
  3. 它允许您在网址级别登录,例如:https://user:password@your.domain.com/login(例如,Chrome会自动将其转换为Authorization标题)
  4. 重要:
    正如@zaph在下面的评论中指出的那样,将敏感信息作为GET查询发送并不是一个好主意,因为它最有可能最终出现在服务器日志中。

    enter image description here

答案 2 :(得分:14)

您可以使用质询响应方案。假设客户端和服务器都知道秘密S.然后服务器可以确定客户端知道密码(不给它):

  1. 服务器将随机数R发送给客户端。
  2. 客户端将H(R,S)发送回服务器(其中H是加密散列函数,如SHA-256)
  3. 服务器计算H(R,S)并将其与客户端的响应进行比较。如果匹配,则服务器知道客户端知道密码。
  4. 修改

    这里存在一个问题,即R的新鲜度以及HTTP无状态的事实。这可以通过让服务器创建一个秘密,称之为Q,只有服务器知道来处理。然后协议如下:

    1. 服务器生成随机数R.然后发送给客户端H(R,Q)(客户端无法伪造)。
    2. 客户端发送R,H(R,Q),并计算H(R,S)并将其全部发送回服务器(其中H是加密散列函数,如SHA-256)
    3. 服务器计算H(R,S)并将其与客户端的响应进行比较。然后它需要R并计算(再次)H(R,Q)。如果客户端的H(R,Q)和H(R,S)版本与服务器的重新计算相匹配,则服务器认为客户端已经过身份验证。
    4. 要注意,由于H(R,Q)不能由客户端伪造,因此H(R,Q)充当cookie(因此可以实际上作为cookie实现)。 /击>

      另一个编辑:

      之前对协议的编辑是不正确的,因为任何观察过H(R,Q)的人似乎都能够用正确的哈希重放它。服务器必须记住哪些R不再新鲜。我正在CW这个答案,所以你们可以编辑这个并找出一些好的东西。

答案 3 :(得分:10)

如果您的虚拟主机允许,或者您需要处理敏感数据,请使用HTTPS,期限。 (法律通常要求afaik)。

否则,如果您想通过HTTP执行某些操作。我会做这样的事情。

  1. 服务器将其公钥嵌入登录页面。
  2. 客户端填充登录表单并单击“提交”。
  3. AJAX请求从服务器获取当前时间戳。
  4. 客户端脚本连接凭据,时间戳和盐(来自模拟数据的散列,例如鼠标移动,按键事件),使用公钥对其进行加密。
  5. 提交结果哈​​希。
  6. 服务器解密哈希
  7. 检查时间戳是否足够近(仅允许短5-10秒的窗口)。如果时间戳太旧,则拒绝登录。
  8. 存储哈希值20秒。在此间隔期间拒绝用于登录的相同哈希。
  9. 对用户进行身份验证。
  10. 因此,密码受到保护,无法重播相同的身份验证哈希。

    关于会话令牌的安全性。那有点难了。但是有可能重新使用被盗的会话令牌。

    1. 服务器设置一个包含随机字符串的额外会话cookie。
    2. 浏览器会在下次请求时发回此Cookie。
    3. 服务器检查cookie中的值,如果它不同则会破坏会话,否则一切都没问题。
    4. 服务器再次使用不同的文本设置co​​okie。
    5. 因此,如果会话令牌被盗,并且其他人发送了请求,那么在原始用户的下一个请求中,会话将被销毁。因此,如果用户主动浏览网站,经常点击链接,那么小偷就不会对被盗令牌走得太远。可以通过对敏感操作(例如删除帐户)进行另一次身份验证来强化此方案。

      编辑:请注意,如果攻击者使用不同的公钥设置自己的页面并代理对服务器的请求,则这不会阻止MITM攻击。 为防止出现这种情况,必须将公钥固定在浏览器的本地存储中或应用程序中以检测这些技巧。

      关于实现:RSA可能是最常见的算法,但对于长密钥来说它很慢。我不知道PHP或Javascript实现的速度有多快。但可能有更快的算法。

答案 4 :(得分:4)

我会使用服务器端和客户端Diffie-Hellman密钥交换系统与AJAX或多个表单提交(我推荐前者),虽然我没有在互联网上看到任何好的实现。请记住,MITM总是可以破坏或更改JS库。在某种程度上,本地存储可用于帮助解决这个问题。

答案 5 :(得分:3)

您可以使用SRP在不安全的频道上使用安全密码。优点是,即使攻击者嗅探流量或破坏服务器,他们也无法在不同的服务器上使用密码。 https://github.com/alax/jsrp是一个javascript库,支持在浏览器或服务器端(通过节点)通过HTTP进行安全密码。

答案 6 :(得分:1)

HTTPS非常强大,因为它使用非对称加密技术。这种类型的加密不仅允许您创建加密隧道,还可以验证您是否与正确的人交谈,而不是黑客。

这是使用非对称密码RSA(由PGP使用)进行通信的Java源代码: http://www.hushmail.com/services/downloads/

答案 7 :(得分:0)

您可以使用ssl作为主机,有像letsencrypt这样的ssl免费项目 https://letsencrypt.org/

答案 8 :(得分:0)

在这里使用https听起来是最好的选择(如今,证书并不那么昂贵)。但是,如果需要http,则可以使用一些加密方式-在服务器端进行加密,然后在用户浏览器中进行加密(单独发送密钥)。

我们在实现safevia.net时就使用了该方法-加密是在客户端(发送者/接收者)端完成的,因此用户数据在网络层或服务器层上均不可用。