我应该在将密码发送到服务器端之前对其进行哈希处理吗?

时间:2010-08-02 19:52:00

标签: security authentication login https

我注意到大多数网站通过HTTPS将密码作为纯文本发送到服务器。有没有什么优势,而不是我发送密码的哈希到服务器?它会更安全吗?

13 个答案:

答案 0 :(得分:135)

这是一个老问题,但我觉得有必要就这个重要问题提出我的意见。这里有很多错误信息

OP从未提及通过HTTP发送密码 - 仅使用HTTPS,但许多人似乎都在回应因某种原因通过HTTP发送密码的问题。那说:

我认为绝不应该以纯文本保留密码(更不用说传输)了。这意味着不会保留在磁盘上,甚至不会留在内存中。

在这里回复的人似乎认为HTTPS是一个银弹,但事实并非如此。然而,它肯定会有很大帮助,并且应该在任何经过​​身份验证的会话中使用。

确实无需知道原始密码是什么。所需要的只是生成(并可靠地重新生成)身份验证的可靠方法"密钥"基于用户选择的原始文本。在理想的世界中,这个文本应该立即生成一个"密钥"用不可逆的盐对其进行散列。此salt对于生成的用户凭据应该是唯一的。这个"关键"将是您的系统用作密码的内容。这样,如果您的系统将来会受到攻击,这些凭据将只对您自己的组织有用,而且在其他任何地方,用户都懒惰并使用相同的密码。

所以我们有一把钥匙。现在我们需要清理客户端设备上的任何密码跟踪。

接下来,我们需要为您的系统获取该密钥。你绝不应该在明确的#34;中传输密钥或密码。甚至不是通过HTTPS。 HTTPS不是不可穿透的。实际上,许多组织可以成为受信任的MITM - 不是从攻击的角度来看,而是对流量进行检查以实现自己的安全策略。这削弱了HTTPS,并不是它发生的唯一方式(例如重定向到HTTP MITM攻击)。永远不要认为它是安全的。

为了解决这个问题,我们用一次性的随机数来散列密钥。此随机数对于每次提交系统密钥都是唯一的 - 即使在同一会话期间,如果您需要多次发送,也会使用相同的凭据。一旦它到达您自己的系统,您就可以撤消该nonce以恢复身份验证密钥,并对请求进行身份验证。

此时,我会在永久存储在您自己的系统中之前不可逆转地将其哈希。这样,您可以为了SSO等目的与合作伙伴组织共享凭据,同时能够证明您自己的组织不能冒充用户。这种方法的最佳部分是,您永远不会在未经授权的情况下共享用户生成的任何内容。

做更多的研究,因为它有更多的内容,甚至我已经泄露,但如果你想为你的用户提供真正的安全性,我认为这种方法目前是最完整的回应。

TL; DR:

使用HTTPS。 使用每个密码的唯一salt安全地哈希密码,不可逆转。在客户端上执行此操作 - 不要传输其实际密码。将用户原始密码传输到您的服务器永远不会#34; OK"或"罚款"。清除原始密码的任何痕迹。 无论HTTP / HTTPS如何,都使用nonce。它在许多层面上都更加安全。 (对OP的回答)。

答案 1 :(得分:22)

由于它是通过HTTPS进行的,因此在没有散列的情况下发送密码绝对没问题(通过HTTPS,它不是明文)。此外,如果您的应用程序依赖于HTTPS来保证其内容的安全性,那么在通过HTTPS发送密码之前对密码进行散列是没有用的(即如果攻击者可以解密线上的数据,则无论如何都会被搞砸)

答案 2 :(得分:17)

不,实际上这将是一个漏洞。如果攻击者能够从数据库中获取哈希值,那么他可以使用它进行身份验证而无需破解它。在任何情况下,用户或攻击者都无法获得哈希密码。

散列密码的重点是添加额外的安全层。如果攻击者能够使用SQL注入或不安全的备份从数据库中获取哈希和盐,那么他必须通过强制查找纯文本。 John The Ripper通常用于破坏盐渍密码哈希值。

不使用https违反了OWASP Top 10:A9-Insufficient Transport Layer Protection

修改 如果在您的实现中计算sha256(client_salt+plain_text_password),然后计算服务器端sha256(server_salt+client_hash)上的另一个哈希,那么这不是一个严重的漏洞。但是,它仍然容易被窃听和重放请求。因此,这仍然明显违反了WASP A9。但是,这仍然使用消息摘要作为安全层。

我所看到的最接近https的客户端替换是diffie-hellman in key exchange in javascript。然而,这确实阻止了MITM的主动攻击,因此直到技术性违反了OWASP A9。代码的作者同意这不是HTTPS的完全替代品,但它总比没有好,比客户端散列系统更好。

答案 3 :(得分:8)

通过线路发送哈希完全违背了哈希的目的,因为攻击者可以简单地发送哈希并忘记密码。简而言之,一个在明文中使用哈希值进行身份验证的系统是公开的,并且只能通过网络嗅探来妥协。

答案 4 :(得分:6)

明文显示的密码永远不会(甚至在使用HTTPS时)离开客户端。它应该在离开客户端之前进行不可逆转的散列,因为服务器不需要知道实际的密码。

Hashing然后传输解决了在多个位置使用相同密码的懒惰用户的安全问题(我知道我这样做)。然而,这并不能保护您的应用程序,因为黑客可以访问数据库(或以任何其他方式获得哈希),因为黑客只能传输哈希并让服务器接受它。

要解决此问题,您当然可以散列服务器接收的哈希值,并在一天内调用它。

我正在创建的基于套接字的Web应用程序中的问题的方法是,在连接到客户端时,服务器生成一个盐(在散列之前添加随机字符串)并将其存储在套接字变量上,然后它将此哈希传输到客户端。在将数据传输到服务器之前,客户端获取用户密码,散列它,从服务器添加盐并散列整个内容。然后将其发送到服务器,该服务器将此哈希值与哈希值(DB + salt中的哈希值)进行比较。据我所知,这是一个很好的方法,但公平地说,我没有读过很多关于这个主题的内容,如果我对任何事情都错了,我很乐意纠正:)

答案 5 :(得分:3)

如果您希望通过HTTPS使用哈希密码替换通过HTTPS的明文密码,那么您就会遇到麻烦。打开通信通道时,HTTPS会生成随机的共享事务密钥。这很难破解,因为你几乎只限于强制用于(相对)短期交易的共享密钥。你的哈希可以被嗅探,离线并在彩虹表中查找,或者只是在很长一段时间内被强制使用。

但是,通过HTTPS发送的基本客户端密码混淆(非散列)确实有一些价值。如果我没有弄错,这种技术实际上是由一些银行使用的。此技术的目的不是保护密码免受嗅探。相反,它是阻止密码可用于愚蠢的间谍工具和浏览器插件,只需获取他们看到的每个HTTPS GET / POST请求。我看到从恶意网站捕获的日志文件是从用户会话捕获的400MB随机GET / POST事务。您可以想象,仅使用HTTPS的网站会在日志中显示明文密码,但是具有非常基本混淆(ROT13)的网站也会显示不能立即使用的密码。

答案 6 :(得分:2)

使用HTTP摘要 - 它甚至通过http保护密码(但最佳用途是通过https进行http摘要)

百科:

HTTP摘要访问身份验证是Web服务器可以用来与Web用户协商凭据(使用HTTP协议)的商定方法之一。摘要式身份验证旨在取代未加密使用的基本访问身份验证,允许安全地建立用户身份,而无需通过网络以明文形式发送密码。摘要式身份验证基本上是MD5加密哈希的应用程序,使用nonce值来防止密码分析。

链接:http://en.wikipedia.org/wiki/Digest_access_authentication

如果你想看到“真实生活”的使用,你可以看一下phpMyID - 一个使用http摘要认证的{php}的开放式提供商http://siege.org/phpmyid.php

..或者您可以从http://php.net/manual/en/features.http-auth.php

的php身份验证示例开始

Http digest rfc:http://www.faqs.org/rfcs/rfc2617

从我的测试中,所有现代浏览器都支持它......

答案 7 :(得分:2)

免责声明:我不是一个安全专家 - 我发布了希望,其他人会批评我的立场过于谨慎或可以改进,我会从中学习。话虽如此,我只想强调一下,当它离开你的客户端时散列并不意味着你不必在将其放入数据库之前在后端进行散列。

同时执行

两者都是因为:

  1. 对搭载的影响有助于弥补传输漏洞,如果SSL连接受到威胁,他们仍然无法看到原始密码。在能够模仿授权用户方面无关紧要,但它可以保护您的用户免于与他们的电子邮件相关联地阅读他们的密码。大多数人都没有遵循最佳做法,并为他们的许多帐户使用相同的密码,因此这对访问者来说可能是一个严重的漏洞。

  2. 如果某人能够以某种方式从数据库中读取密码(这确实发生了,请考虑SQL注入),他们仍然无法执行通过我的API模拟用户的特权操作。这是因为哈希不对称;即使他们知道存储在您的数据库中的哈希,他们也不会知道用于创建它的原始密钥,而这正是您的身份验证中间件用于进行身份验证的内容。这也是为什么你应该总是为你的哈希存储加盐。

  3. 当然,如果他们可以自由地从数据库中读取他们想要的内容,他们可能会造成很多其他损害。

    我只想在此强调,如果您决定在离开客户之前对密钥进行散列,这还不够 - 后端散列是非常重要的,这就是为什么:如果有人在拦截来自您客户的流量,然后他们将看到password字段的内容。无论是哈希还是纯文本,都无关紧要 - 他们可以逐字复制以模仿授权客户端。 (除非你按照@ user3299591概述的步骤进行操作,我建议你这样做)。另一方面,散列数据库列是必要的,而且根本不难实现。

答案 8 :(得分:1)

如果您已连接到https服务器,则应加密服务器和浏览器之间的数据流。数据在发送之前和收到之后只是纯文本。 Wikipedia article

答案 9 :(得分:1)

如果您想获得与通过 https 传输时相同的可靠性,那么是 - 一种选择 - 在 ajax 级别实现非对称加密通道。

如果我们不是在谈论注册(例如,密码的第一次传输始终受到保护),那么还有一些选项。

例如

  1. 服务器生成一个随机字符串并生成一个发送给用户。
  2. 用户从他的密码中计算出一个哈希值,并使用这个哈希值作为 例如,一个密钥用一个 bluesh 加密这个随机字符串(那里 肯定是 JS 中的实现)并将其发送回给您。
  3. 您自己使用存储在服务器上的哈希值也对其进行加密 带有 blueshish 的随机字符串。
  4. 比较。

攻击者必须使用随机源和密文来攻击 bluefish 密钥。这项任务并不容易。

答案 10 :(得分:0)

散列密码并通过非加密通道发送密码实际上不太安全。您将在客户端上公开散列算法。黑客可以只是嗅探密码的哈希值,然后用它来破解密码。

通过使用HTTPS,您可以阻止黑客从单一来源获取密码,因为HTTPS使用两个加密的通道。

答案 11 :(得分:0)

是不是SSL / TLS取代了nonce?我没有看到这个的附加价值,因为SSL / TLS也可以防止重播攻击。

参考。 https://en.wikipedia.org/wiki/Cryptographic_nonce

答案 12 :(得分:0)

是否有优势,以及它是否更(或更不安全)真正取决于实现。可以说存在一些优势,但是如果实施不当,则肯定可以创建一种解决方案,其安全性甚至不及传递纯文本密码。

这可以从两种攻击的角度来看:一种可以访问网络流量,另一种可以访问数据库。

如果攻击者可以截获网络流量的纯文本版本,则看到密码的哈希值比看到纯文本的密码更安全。尽管攻击者仍然可以使用该哈希登录到您的服务器,但它需要对该哈希进行蛮力破解(有时是预先计算)才能确定在其他系统上可能有用的密码。人们应该在不同的系统上使用不同的密码,但通常不要这样做。

如果攻击者可能通过备份的副本获得了对数据库的访问权限,那么您将要确保仅凭这一知识就无法登录。例如,如果您存储的哈希值的登录名为hash(login_name+password),并且从客户端传递了相同的哈希值以进行直接比较,则攻击者可以随机选择一个用户,然后从数据库并以该用户身份登录而无需知道密码,从而扩大了违反范围。在这种情况下,以明文形式发送密码会更加安全,因为攻击者需要知道明文才能登录,甚至拥有数据库副本也是如此。 这是实现的关键。无论您发送明文密码还是该密码的客户端哈希,都应在服务器端对该值进行哈希处理,然后将该哈希值与存储在服务器端的哈希值进行比较。用户记录。

要记住的概念:

  • 您可以通过将某种范围唯一的值混入哈希(通常是行唯一的)来“加盐”哈希。其目的是即使哈希表示的纯文本值相同,也可以确保彼此唯一的哈希,因此具有相同密码的两个用户仍将具有不同的哈希。不必把盐当作秘密。
  • 进行身份验证时,请始终在服务器端对从客户端作为密码传递的任何值进行哈希处理(即使该值已被哈希化),并将其与数据库中存储的预哈希值进行比较。这可能需要存储原始密码的双哈希版本。
  • 进行哈希处理时,请考虑在哈希中添加服务器/集群唯一的盐以及行唯一的盐,以防止与查找表中的任何预先计算的哈希匹配。