在客户端散列密码是不是具有安全意义
Posted
技术标签:
【中文标题】在客户端散列密码是不是具有安全意义【英文标题】:Does it make security sense to hash password on client end在客户端散列密码是否具有安全意义 【发布时间】:2010-11-25 16:41:05 【问题描述】:如果您在跨线路发送用户密码之前对其进行哈希处理并将其以纯文本形式保存在内存中,这会提高应用程序的安全性吗?
我认为这可以通过保护存储在客户端内存中的数据来缓解一小部分漏洞。但实际上,如果我们担心有人会读取客户的记忆,那么我们可能无法解决更大的问题。
在客户端进行哈希处理有些不妥。
客户端上的密码散列是一种常见的做法吗?这样做还有其他优点或缺点吗?
编辑: 鉴于通信通道是安全的 (SSL)。在什么条件下使用这种方法是可以接受和值得的。我问这个是因为“安全专家”建议我在某些应用程序功能中使用这种方案。
【问题讨论】:
接受的答案是错误的。 它确实给了您一个优势, 前提是您也可以在服务器端对哈希本身进行盐哈希处理。见security.stackexchange.com/a/23285/2379,security.stackexchange.com/a/23033/2379 【参考方案1】:没有。
当客户端发送某事时,无论是P
或H(P)
或H(H(P))
,任何拦截此内容的人都可以简单地重新发送完全相同的东西,因此使任何这样的功能都等同于直接使用密码。
这就是为什么你应该使用nonce;服务器可以发出一些随机垃圾k
,客户端将计算H(P,k)
并将其发送给服务器。 HMAC 是这种方法的流行实现。
如果服务器从不两次接受相同的随机数,这对于重放攻击是安全的。
【讨论】:
... 但这创造了一个 DoS 机会:捕获发送给客户端的每个服务器随机数,并在合法客户端之前使用它;瞧,现在客户端根本无法登录,因为在客户端发送请求时,每个随机数都已经过期。不是一个完全实用的场景,但与往常一样,安全性需要与可用性保持平衡,有时添加一个会降低另一个。 正如其他答案所指出的,在客户端散列有一些轻微优势,因为许多用户在多个服务中重复使用密码。 @geocar:我同意你的主要观点,如果你依赖它来实现端到端安全,那么你做错了;我同意你关于使用 nonce/HMAC 来加强它的建议。我只是不同意您的绝对声明,即客户端散列绝对没有好处 - 在其他答案中,Lucas Oman、David Thornley 和 user1700819 都指出了散列对客户端的潜在轻微好处。 ...我可能在这里误解了一些东西 - 如果我是,请随时纠正我 - 但 HMAC 不要求双方共享相同的密钥,对吗?在这种情况下,如果站点使用基于密码的身份验证,但不散列客户端,那么数据库必须直接存储密码,否则无法验证 HMAC。这本身就会构成一个严重的漏洞。一个可以通过使用 HMAC 的 H(K=password, m=username) 而不是直接使用密码来改善的漏洞 - 对用户或应用程序主机没有可见的成本。 如果您实际上并不需要密码本身(以及担心如果有人破解您的服务器会同时泄露每个人的密码的相关开销),那么存储加密密码是愚蠢的,而您不需要.您真正需要的只是身份验证令牌。【参考方案2】:正如其他人所指出的那样,发送散列密码不会提高您网站的安全性(因为您接受散列密码,所以坏人只需要知道散列版本)。它也不是很安全,因为坏人可能会加载您的登录页面并检查部署的 javascript 或 Java。
它的作用是防止有人看到数据包提取密码,这是相当有用的。许多人在多个网站上使用相同的密码(除了安全性较高的网站,我对所有网站都使用相同的密码),因此如果您能从他们那里获得一个密码,您就可以在其他网站上登录其他帐户。
它还可以防止将真实密码存储在您的网站上,即使是暂时的,如果您的网站遭到入侵,这可能会提供一些额外的安全性。
因此,虽然我认为用户端散列可能是一件好事,但不值得多费心。
而且,正如其他人告诉您的那样,不要自行设置安全性。有太多事情可能出错。你不会像一个老练的坏人那样快速地注意到它们。
【讨论】:
It's also not really secure, since the bad guy can presumably load your login page and examine the Javascript or Java deployed.
良好的安全性不应依赖于攻击者不知道您的算法。所以,这一点是虚假的。这是您试图使其更难确定的关键,而不是算法。攻击者还可以查找实现 SSL 的源代码。并不意味着攻击者可以破解 SSL。【参考方案3】:
哈希与您描述的场景中来自安全 POV 的密码相同:如果我拦截了哈希,我不需要知道密码,我可以将拦截的哈希发送给服务器。
Authentication protocols 尽量避免这个问题;安全性很难,您最好选择和实施一个易于理解的协议,而不是自己动手。
如果您的流量是通过 SSL 传输的,那么您就不会被拦截,而哈希算法几乎不会给您带来额外的好处。
【讨论】:
唯一不等效的原因是用户的密码——他可以用于多个帐户——不在野外。 @LucasOman 抱歉,单个基本哈希对保护密码没有任何作用,它提供了一种虚假的安全感。像 hashcat 这样的工具每秒可以在商用硬件上运行数十亿次基本哈希。使其通过客户端哈希提供任何保护的唯一方法是运行具有数万或数十万次迭代的完整 BCrypt/PBKDF2,就像我们在服务器上存储密码一样。这很愚蠢,因为就服务器而言,生成的哈希仍然是密码。只需使用 SSL。 @Tito “单个基本哈希对保护密码没有任何作用”这是一个公然的谎言。 Hashcat 正在进行暴力攻击,这意味着如果密码是任意长度,攻击者将无法猜到它。因此,如果在多个服务中使用相同的长密码,只有散列的攻击者只能在接受该散列的服务上使用它。如果每个这样做的网站都使用相同的散列算法,但使用不同的、特定于供应商的随机数,那么您实际上可以保证散列仅在一个站点上有用。【参考方案4】:是的,你应该这样做。
IEEE 发生了一次数据泄露事件,其中 10 万封电子邮件和密码从一个博客中泄露。
http://ieeelog.com/
显然,IEEE 不应该公开他们的博客!但如果他们在客户端对密码进行哈希处理,情况就不会那么糟糕了。
正如第一个答案所述,您应该使用随机数。如果你使用足够长的随机数(例如 128 位),你真的不需要担心重用,因为服务器永远不会要求相同的随机数两次(假设正确播种 CRNG 等)。
【讨论】:
【参考方案5】:不,客户端的散列不能“完全”保护密码。当一个人选择在客户端对密码进行哈希处理时,提交给服务器的摘要本质上就变成了密码。如果部署了 SSL,这本身就不是问题。
但是,这种方案最终产生的问题多于解决的问题。如果服务器将客户端提交的哈希值与数据库中存储的哈希值进行比较,而不执行任何进一步的加密操作(尤其是对输入数据进行哈希处理),那么 密码以明文形式存储实际目的。任何有权访问存储哈希的人都可以将其重新提交到服务器并获得对帐户的访问权限。
简单来说,如果提交的哈希(与提交的哈希相同)通过应用程序中的任何其他漏洞(例如通过 SQL 注入)泄漏,那么应用程序就有一个漏洞,其中保护了密码不足。
如果必须修复底层漏洞,则有必要将提交的哈希视为明文密码,然后在与存储的哈希比较之前对其进行哈希(最好使用盐)。
【讨论】:
hashing at the client does not protect the password 'completely'
好吧,没有什么可以完全保护密码。如果你的攻击者愿意每分钟杀死一个孩子,直到你让他们在你的 wordpress 博客上发帖,假设你最终会让他们上传所有这些猫的照片。关键是它是否保护密码more,您的答案显然是“不”。 the password is stored in clear text for all practical purposes
不,不是。 身份验证令牌是明文,但密码是隐藏的。
我知道身份验证令牌和密码之间的区别可能看起来很迂腐,但如果我是一个习惯性使用主动核发射代码作为密码的人,或者我是 Rush Limbaugh 并且我的密码是“我杀了1993 年的一个小女孩,这是我具有法律约束力的认罪”,区别非常重要。【参考方案6】:
我认为在一种情况下这是有道理的;您甚至不想知道客户端的明文密码。如果您在客户端进行散列,那么盐和迭代散列该散列的方式与您对纯文本 pw 的散列方式相同。除此之外,它有点傻。
【讨论】:
【参考方案7】:只需确保您通过安全通道 (SSL) 发送密码即可。如果客户端可以读取应用程序私有内存,那么他们很可能有更大的问题,例如键盘记录器。
【讨论】:
【参考方案8】:如果您使用Secure Remote Password protocol (SRP),您的情况会好得多。它就是为此而设计的。
【讨论】:
【参考方案9】:我可以给你不同的方法 如果您没有 SSL,您可以在客户端对密码进行哈希处理,然后使用另一种哈希方法在服务器端再次对其进行哈希处理并将它们存储在数据库中 并且当用户使用密码登录时执行相同的过程并将双哈希密码与存储的哈希匹配
【讨论】:
那里的危险,以及其他 cmets 中提到的其他答案,是 replay attack @George'Griffin - 重放攻击与混淆或加密传输有何特别相关?难道它也适用于明文传输,除非在这种情况下,精确的密码可能会更快甚至无意中被泄露?【参考方案10】:是的,即使您使用 SSL,在客户端对密码进行哈希处理也是有意义的,但您仍然必须在服务器端再次对其进行哈希处理。
这很有意义,尤其是在移动应用的情况下。如果即使使用“常量盐”/域字符串在客户端进行哈希处理,即使使用 SSL,它也会比以明文形式发送密码要好得多。如果您向服务器发送明文密码,那么万一有人入侵您的服务器,他将收到明文密码。因此,在客户端添加额外的预散列可以保护用户和他们可能在其他地方也使用的密码。
您可能会发现很多帖子说不需要客户端散列,但它们通常与 Web 应用程序相关并且不考虑移动应用程序的情况。对于网络应用程序,如果有人入侵服务器,他可以替换网站并删除客户端哈希,所以在这种情况下没有那么大的优势。但是对于移动应用程序,攻击者无法替换移动应用程序的代码,因此在这种情况下,客户端的哈希值很有意义。
您可以查看此链接,了解在客户端和服务器端都使用散列的可能解决方案:https://medium.com/@harwoeck/password-and-credential-management-in-2018-56f43669d588
所以是的,在客户端和服务器端都散列。
【讨论】:
【参考方案11】:客户端的散列打开了另一个巨大的漏洞:你可能会暴露散列算法。您没有说这是基于 Web 的(客户端 = JavaScript)还是胖客户端,但您正在向他们提供更多信息。鉴于通道是安全的,您不必担心明文密码被嗅探。
此外,如果您的散列算法需要盐,您将暴露您的盐,这意味着如果他们能够访问数据库,他们将能够解密每个密码。
【讨论】:
不正确。 1) 安全不应依赖于隐藏正在使用的算法。 2)即使你知道盐,也很难解密密码(假设它们是使用标准方法加密的),除非你有一个“盐”的彩虹表。 这个答案似乎误解了盐的功能。如果您对每个密码都使用相同的盐,那么您做错了,您可能根本不使用盐。以上是关于在客户端散列密码是不是具有安全意义的主要内容,如果未能解决你的问题,请参考以下文章
当我在客户端散列密码时,我没有得到散列字符串,而是获取密码本身