在提交给服务器之前,很少有网站会散列用户密码。 Javascript甚至不支持SHA或其他算法。

但是我可以想到很多优点,例如防止跨站点泄漏或恶意管理的SSL所没有的。

为什么这种做法在网站中如此罕见?

评论

您认为客户端哈希密码有什么优势?

@TimLamballais典型的客户端在散列上花费的时间比服务器要多得多。因此,如果您在客户端中有高性能的实现(在当前浏览器中排除了javascript),则可以使用更昂贵的密码散列,从而更强。这也意味着服务器永远不会看到密码本身。客户端散列也是增强的PAKE协议(如SRP)的先决条件,在该协议中,模拟服务器无法使您访问密码。

Javascript不再那么慢了。现代javascript引擎已经变得如此之快,以至于与编译语言相提并论,而最近的增加(如类型数组)为密码学所需的数字运算提供了适当的工具。

@TimLamballais优点之一是服务器永远不会看到我的真实密码,也不会泄漏它(是的,他们仍然可以泄漏哈希,但是应该对域名加以限制,因此对登录其他站点没有用)。但是,对于最大的优势,请参阅我对Phillip的回答。

许多人质疑这种做法是否会获得额外的安全性。它所做的一件事就是降低风险。如果您始终进行哈希或加密(我见过使用公开密钥对蒸汽/阀门进行加密,并且我敢打赌他们没有解密),那么您就不可能有尴尬的明文后门。不...它不再安全了,但并非毫无意义

#1 楼

JavaScript密码哈希的发明者

早在1998年,我就建立了一个Wiki,这是我用登录系统建立的第一个网站。我无法负担得起使用SSL托管的费用,但我担心通过Internet传输的纯文本密码。我读了有关CHAP(挑战性哈希身份验证协议)的文章,并意识到我可以在JavaScript中实现它。我最终将JavaScript MD5作为一个独立项目发布,并且它已成为我开发的最受欢迎的开源代码。 Wiki从未超越alpha。

与SSL相比,它具有许多弱点:


仅可防止被动窃听。处于活动状态的MITM可以篡改JavaScript并禁用哈希。
服务器端哈希成为等效的密码。至少在通用实现中;可以避免这种情况。
被捕获的哈希值可能被强行使用。从理论上讲,使用JavaScript RSA可以避免这种情况。

我总是在前面提到这些限制。我曾经定期为他们发火。但是直到今天,我仍然坚持原来的原则:如果您出于某种原因未获得SSL,那将比纯文本密码更好。在2000年代初期,许多大型提供商(最著名的是Yahoo!)都使用此软件进行登录。他们认为,即使仅用于登录的SSL也会有太多开销。我认为他们仅在2006年就登录使用SSL,而在2011年Firesheep发布时,大多数提供程序都切换到了完全SSL。而是使用SSL。

客户端哈希还具有一些潜在的好处:


某些软件不知道是否将使用SSL进行部署。 ,因此包含散列是有意义的。 vBulletin是这种情况的常见示例。
服务器缓解-具有计算量大的哈希值,对于客户端来说,做一些工作是有意义的。看到这个问题。
恶意管理员或受感染的服务器-客户端哈希可以阻止他们看到纯文本密码。通常会取消此操作,因为他们可以修改JavaScript并禁用哈希。但公平地说,这种行动增加了他们被发现的机会,因此对此有一些好处。

尽管这些好处最终很小,而且增加了很多复杂性-您确实面临着以下风险:在尝试提高安全性时会引入一个更严重的漏洞。对于需要比密码更高的安全性的人,多因素身份验证是更好的解决方案。

第二个简短的答案是:因为多因素身份验证比客户端密码哈希更安全。 br />

评论


如果服务器受到黑客的攻击,他想从客户端收集普通密码以在其他地方使用它们,该怎么办?没有安全措施,只有客户端哈希。为什么我们必须强制客户端信任服务器?

–КонстантинВан
19年2月4日在7:16

@КонстантинВан-请参考答案的“受损的服务器”部分

–paj28
19年2月4日在10:04

客户端哈希的另一个缺点是您不能在服务器上实施密码策略。基本上,您无法验证用户选择的密码是否足够强

–迈克尔
19年4月16日在6:24

@Michael在我看来,这是一件好事,因为大多数服务器上的密码策略都是荒谬的。无缘无故禁止使用许多密码字符。

–TomášZato-恢复莫妮卡
19年6月18日在10:04

#2 楼

要了解此问题,首先您必须了解我们为什么对密码进行哈希处理。完全有可能以纯文本格式将密码存储在服务器上,并将发送的密码与收到的密码进行比较。只要在传输过程中保护密码,这就是一种安全的身份验证方法(共享机密)。

密码被散列的原因是因为问题不是身份验证,而是存储。如果服务器受到威胁,攻击者将立即访问所有用户帐户,因为他们现在知道用于验证用户身份的机密。

散列对此构成障碍。由于服务器不知道进行身份验证所需的实际输入,因此即使对数据库的妥协也无法授予攻击者访问用户帐户的权限。他们仍然需要找出输入,以提供达到应用程序检查的哈希值。当然,他们可以将所有值更改为他们知道的内容,但这会很快引起怀疑,并且系统将被关闭并受到保护。

因此,客户端哈希处理的问题在于,它有效地使得哈希的结果是密码而不是密码。没有什么可以阻止攻击者绕过官方客户端,而只是将完成的哈希直接发送到服务器。它在身份验证期间不会提供任何额外的(或损失)安全性,但是在哈希旨在防止的情况下,由于存储在数据库中的哈希实际上是传输到服务器的共享机密,因此它没有任何作用。
就是说,客户端哈希确实为您提供了两个值得注意的功能。尽管它根本无法帮助保护您的系统,但可能可以帮助保护您的用户。如果您不安全地传输密码或在不破坏客户端代码的情况下破坏了传输,您仍然可以保护用户密码(他们的密码可以在其他站点上重复使用)免受泄露。

您可以提供哈希的其他迭代,从而在不使用服务器周期的情况下使对数据库的脱机攻击更加困难(同时还延长了“客户端提交的中间密码”的长度),但是您仍然需要足够的服务器周期保护加长密码以防恶意客户端。同样,此方法提供的主要保护措施是防止发现原始密码,但它无助于保护站点的身份验证机制。从服务器的角度来看,应将客户端哈希视为用户的直接密码。与用户直接提供密码并应受到保护一样,它在服务器上提供的安全性没有或多或少的不足。

如果您希望能够提供额外的安全性,我将建议两个哈希。哈希一次客户端以构建一个新的唯一密码,然后将该密码哈希到服务器上以使值存储在数据库中。这样一来,您可以两全其美。

在大多数情况下,SSL被充分信任以保护交换,以至于传输之前的初始哈希值被认为是不必要的,而且受感染的服务器可能总是会改变发送给客户端的代码,这样就不会执行初始哈希。它根本不是SSL的有效替代品,并且没有提供足够的额外优势来值得付出成本和复杂性。

评论


我需要在客户端加密一些数据,并且通过仅将哈希发送到服务器,可以证明服务器无法解密本地数据,因为它不知道纯文本密码。此外,在用域名对哈希值加盐时,有一个保证,即服务器永远不会泄漏我的密码,而只是加盐(无用)的哈希值。

–美斯
2014年3月18日在13:46

@Muis-我的意思仅仅是,在处理服务器端时,应将哈希生成的客户端视为用户自己的密码。使用客户端的哈希值来保护用户的密码不被服务器暴露是不错的选择,但是就服务器而言,它实际上就像用户的直接密码一样。

– AJ亨德森
2014年3月18日13:52

为什么不那么简单地同时做两个呢?在客户端进行哈希处理以避免泄漏实际的明文密码,并在服务器端再次进行哈希处理以避免哈希成为密码问题。

– Xaser
16年8月27日在8:29

@uhfocuz不。出于很多原因,完全没有。主要问题是,出于登录目的,客户端哈希将是用户的密码,而不是用户键入的任何密码,因为服务器无法验证客户端的身份。此外,在提供页面内容的通道上没有保护的情况下,中间的人可能会简单地完全剥离客户端哈希并捕获用户密码。最后,即使没有这些问题,除非密码所代表的熵程度与SSL中所使用的密钥相同,否则暴力破解哈希冲突将更加容易。

– AJ亨德森
16年8月28日在5:19

@uhfocuz,这就是我的意思。它没有提供更安全的媒体。两种不同的哈希算法并不重要。我从未说过您不能执行客户端哈希,只是说客户端哈希的本质确实不能为您提供任何安全性方面的信息。它仅保护在多个地方使用同一强密码的用户,避免将密码发送到服务器。对于很多工作而言,这是一个非常有限的优势,而且可能增加xss表面积。

– AJ亨德森
16年8月28日在17:45

#3 楼

如果您有很多优点,则应在问题中列出它们,以便人们了解它们是否真正有用(如果这样,您可能会成名;)

人们不喜欢客户端哈希,因为它们具有保护用户私人信息的更好方法。让我们考虑一下存在潜在信息泄漏的地方,其中有三个:


客户端。
客户端和服务器之间。
服务器。

然后让我们看看为什么客户端哈希在这些地方会有所帮助。



客户端。

如果您自己的计算机上存在恶意软件,例如,如果您的浏览器被破坏或您的计算机植入了密钥记录软件,则客户端哈希不会阻止黑客获取您的密码。原因很明显。


在客户端和服务器之间。

客户端和服务器之间存在通信通道。如果有一个窃听者在监听通信,则客户端哈希可以使密码泄漏更加困难,因为窃听者必须从其哈希中恢复原始密码。

但是,此漏洞是基于不安全的通信渠道的前提。实际上,有些协议的存在试图准确解决此问题。他们的主要任务是在不安全的通道上建立安全通道。最著名且部署最广泛的示例是SSL / TLS,它比客户端哈希提供更多的功能和更好的安全性。是更好的工具。


服务器。

如果服务器被黑客攻陷,则用户信息可能会在服务器上泄漏。如果用户密码以明文形式存储,则黑客可以从数据库中获取用户密码。这就是为什么今天大多数服务器不这样做的原因。而是存储密码的哈希值,以使黑客无法轻易地从手头的信息中还原原始密码(即哈希值)。存储在客户端计算的哈希值。但这是严重错误的。在这种情况下,散列本身变成了密码等效项。黑客可以通过简单地移交哈希而不反转哈希来通过身份验证。黑客的目标不是反转哈希,而是闯入您的帐户。重要性在于服务器对客户端数据的验证过程,而不是数据是哈希值。因此,客户端哈希处理的好处在这里是微不足道的,并且服务器无论如何都必须重新哈希。


总而言之,客户端哈希处理有助于保护用户信息,但是这种保护在很大程度上适用于沟通渠道。由于我们在那里有更好的方法(SSL / TLS),因此客户端哈希的应用受到了极大的压制。这根本不是解决当前任务的最佳工具。

评论


回复:这句话:“黑客的目标不是反转哈希,而是侵入您的帐户。”我会说这取决于网站是什么。通常,用户密码比访问该站点更有价值,希望该口令可以在其他具有更大访问价值的站点上使用。

– TTT
16年11月29日在15:00

@TTT从上下文来看,这句话实际上意味着黑客只要获得所需的私人信息就不会在乎它是哈希密码还是纯文本密码。

– Cyker
16-11-30在2:39



这个答案超级有帮助。

– NDiaz
16年11月30日在19:31

我同意TTT。我不同意客户端(以您所说的那样)以明文形式发送其密码(而不是添加盐值的哈希)是“更好的”。这带来了某些服务器端代理由于恶意或过失而窃取或泄漏客户端密码的风险。由于许多用户都在交叉使用密码,因此这是一个非常令人担忧的风险。

–杰伊·沙利文(Jay Sullivan)
16 Dec 24'2:32

因此,您的答案摘要是“因为我看到的只是轻微的优势”?不是因为仅在服务器上执行快速散列而在客户端上执行慢散列有任何缺点吗?我在此答案中对主题做了一些详细说明,很想听听您的想法。

–吕克
19年1月9日23:30

#4 楼

优良作法是在客户端进行哈希处理,然后对密码加盐并在服务器端再次进行哈希处理。这是针对中间攻击中人的额外防护层。 SSL是第一层,但是Snowden的启示明确表明SSL可以相对容易地被NSA等组织破坏。

评论


这个答案没有提供其他答案不能提供的任何东西,并且错过了MitM的要点,即可以使用客户端的密码哈希,就好像密码本身一样。

–马克
2015年5月5日在8:29

@马克嗯没有马克。这确实有助于mitm。 Mayhem表示将再次哈希哈希密码。

–卡尔·莫里森(Karl Morrison)
16年1月28日在22:02

这是我没想到的好主意。在客户端进行哈希处理以隐藏纯文本密码,然后在服务器端进行哈希处理以防止服务器端受到破坏。感谢分享!

–亚伦·吉利恩(Aaron Gillion)
16年4月15日在23:55

@Karl,“中间人”仍将提供与目标用户相同的请求参数。仅仅因为它不是密码,并不意味着攻击者无法拦截该哈希并将该哈希提供给服务器(让它“哈希”并成功匹配)。

– zyglobe
16-10-26在3:25

@RedGlobe这是事实。但这确实有帮助,因为大量的互联网用户对所有内容使用相同的密码。我同意这可能不利于该特定系统,但是它将在更大范围内有所帮助。

–卡尔·莫里森(Karl Morrison)
16-10-26在8:48

#5 楼

客户端密码散列有什么优势?

密码不会以明文形式通过网络发送。但是登录时确实应该使用TLS加密,因此密码嗅探不会成为问题。

另一个原因可能是您不希望服务器知道用户密码,甚至不会持续一微秒。这意味着您在注册时为服务器提供了密码哈希,然后使用该密码哈希登录。不幸的是,这并不能解决任何问题:登录帐户的共享机密现在是哈希,而不是密码。当您了解哈希值后,就可以在不知道实际密码的情况下登录(因为服务器也不知道该密码)。

评论


对我来说,这样做的好处是,我可以使用用户的密码来加密我的应用程序中的某些本地数据,并证明服务器永远无法解密该数据(因为它仅知道哈希值)。否则,我将有两个提示最终用户输入两个不同的密码(1个用于登录,1个用于加密)。

–美斯
2014年3月18日13:41

@Muis在这种情况下,答案将是“因为没有人像您这样有异乎寻常的要求”。

– Philipp
2014年3月18日13:54



@Muis,您对“证明”的定义必须很弱,因为由于字典攻击非常成功,因此通常对哈希的了解等同于对密码的了解。我确实明白你的意思。可以证明用户是否选择了正确的密码。

– Mikeikeazo
2014年3月18日在15:30

@Muis盐腌不是这样。盐只能防止预先计算的彩虹表,而不能防止字典攻击。

– Philipp
2014年3月18日在16:01



@ Philipp,Salt可以防止字典攻击,因为攻击者只希望从捕获的哈希中选择一个即可。它无助于针对单个散列的字典攻击。

– Mikeikeazo
2014年3月18日在16:53

#6 楼

由于您正在谈论Web应用程序...

在数据库中,我们有一个表调用dbo.useracc,我们将这些哈希值存储在密码中。

User        Password
--------       ----------
user1       5f4dcc3b5aa765d61d8327deb882cf99
user2       202cb962ac59075b964b07152d234b70
user3       098f6bcd4621d373cade4e832627b4f6


和我们在Web应用程序中的登录功能类似

if (user == $user and password == $pass) {
           return auth.token
}


假设攻击者成功入侵并窃取了数据库并保存了dbo.useracc数据。现在,他已经有了我们的哈希密码。发送您的哈希密码,他仍然可以登录。请记住,您的应用程序数据在经过哈希处理以进行检查之后最终会通过POST方法与服务器进行通信。

但是,如果哈希处理在服务器中,则是另一回事了。

$pass = md5.hash($pass);

if (user == $user and password == $pass) {
           return auth.token;
}


如果黑客使用哈希密码登录,则将使用哈希密码对哈希密码进行检查。

在这种情况下,假设攻击者发布

$ user = user1
$ pass = 5f4dcc3b5aa765d61d8327deb882cf99

在服务器端执行$ pass = md5.hash(5f4dcc3b5aa765d61d8327deb882cf99)它将返回'696d29e0940a4957748fe3fc9efd22a3',这将返回错误的语句。使用哈希密码。当然,如果攻击者通过字典攻击成功地对暴力破解/破解了哈希,那么攻击者仍然可以入侵这些帐户。但是,如果密码在破坏系统后是一个好的密码,则黑客需要更长的时间,并且服务器管理员可以重置密码并向用户发送电子邮件。

此外,它还用于应对内部威胁,例如企业中的员工。在企业中,将有数据库管理员和开发人员。他们是不同的角色。现在,为了防止员工用户访问敏感数据,他们需要同时访问应用程序和数据库才能访问数据。当然,您可能会争辩说,DBA仍然可以通过数据库本身来更改数据库数据,但是开发人员无法访问它,并且更容易确定攻击的来源。它与访问控制权有关,并将风险和威胁降至最低。

评论


您是正确的,它不会使攻击者更难使用被盗的哈希值进入我的网站,但它会使登录到另一个网站更加困难,因为另一个网站很可能不使用完全相同的salt +哈希算法。

–美斯
2014年3月18日14:04

只要ANOTHER网站不在客户端中进行哈希运算,攻击者就无法使用哈希密码访问ANOTHER网站,这是一个很好的密码,很难通过字典或Rainbow Table攻击进行强力攻击。作为开发人员,您为什么首先要关心“ ANOTHER”网站。如果用户非常重视其他数据,则应练习不要使用全局密码。

–天空
2014年3月18日14:11



#7 楼

尽管该主题有一些具体的泄漏点,如@Cyker所指出的,但这里的讨论还是有点轻快的。。。简而言之,如果您尽快进行哈希处理,则可以减少意外将明文密码传递到不应传递的地方的编程风险。我们已经采取了安全字符串和安全数组之类的措施来尝试尽快销毁明文。在获得密码的同时进行哈希运算是另一种类似的措施……随着代码的发展等,这种风险似乎仍在降低。

我只是写了一个C#“ Box”,接受SecureString明文并立即对其进行哈希处理---这样,我只知道它永远不会被记录或传递给我不希望的库。这与协议无关,而只是程序员坐在这里看着密码---我不想触摸它! (在某些方面,它仍然是等效的密码,但是至少可以立即将其隐藏起来,就像在链接的方法调用中移动右括号并将明文传递到错误的位置一样。而且仍然没有隐藏安全数组。) />

#8 楼

我打算以权衡明确的目的加入到这里,以支持客户端哈希机制。让我们看看这对我们有何好处:

客户端:
没有任何改进。

传输中:
在SSLstrip情况下保护密码密码最终以明文形式传输。但是,如果实施了HSTS,那么大多数人会说SSLStrip将不起作用。是吗?
否。

进入服务器时:
最后,我们看到了最大的好处。如果有人破坏了服务器怎么办?如果他们只是启动Wireshark / TCPDump并导出服务器的私钥,他们将获得连续的明文密码流。现在,他们可以坐在网络上几个月,而对于高容量的服务器(每月数百万个用户注册),他们将遇到大量纯文本漏洞。当然,这是假定为服务人员获取密码比在服务器上拥有RCE更具价值。

在服务器上:
如果没有,性能优势不必在每个输入的密码上运行bcrypt,这样就可以在不引入任何新漏洞的情况下,将一些计算量分担给客户端。对于服务器管理员和硬件成本来说,这似乎是一件好事。

看起来,最佳实践似乎是将密码哈希合并到客户端,除非它会造成无法忍受的页面加载时间为用户。

评论


我很想知道为什么有人不赞成这个答案。 SSLStrip有点过时了,但没有错,其余答案对我来说似乎很准确。

–吕克
19年1月9日在23:33

我当然不知道重读几年前的评论,我在推理中看不出任何明显的缺陷。

– DeepS1X
19 Mar 13 '19在6:03

#9 楼

我同意如果可以使用SSL / TLS,则客户端哈希保护身份验证过程的优势将受到限制。
但是,如果攻击者可以访问存储的哈希值(此过程之后),则SSL / TLS无法解决针对自定义硬件攻击的漏洞。诸如简单的盐渍哈希之类的功能或诸如PBKDF2之类的功能由于对内存的需求低而非常容易受到这些攻击。受这些方案保护的密码破解既便宜又快速。这至少是密码哈希处理的主要问题之一。

乍一看,这与客户端哈希处理与SSL / TLS无关-而是:
实现诸如Scrypt,Argon2或Catena之类的内存硬密码哈希方案以保护自定义硬件攻击,服务器的硬件需求急剧增加。因此,实际上,服务会降低内存硬度或切换到易受攻击的方案。客户端哈希可以帮助解决该问题。当客户端计算这些昂贵的(内存硬性)功能时,该服务可以使用它们而无需更好的硬件。

因此,现代密码哈希方案可以委托最昂贵的(内存硬性)功能部分功能提供给客户。此功能称为服务器缓解,由Argon2和Catena提供。

结论:使用现代的密码散列方案非常不容易受到自定义硬件的攻击,将来会增加或至少应该增加对客户端散列的使用,当然还有SSL / TLS。

#10 楼

我认为客户端哈希有一个弊端:

pro:在dns / phishing / whatthing的情况下,您可以隐藏密码,这对用户很有用,因为大多数人在多个密码上重复使用服务。正如其他开发人员所说,这对您自己的安全无济于事。

缺点:您的服务器未获得密码,这可以防止类似警告用户密码强度的事情。我知道有人会说这可以/应该是客户端,但是当您有多个客户端时,这可以很好地集中服务器端。

评论


(我没有拒绝投票,如果人们可以解释一下反对票,那就太好了。)密码建议实际上应该在客户端进行。我建议使用像zxcvbn这样的库,它可以以多种不同的语言提供,并且似乎非常面向目标并且经过精心设计。这也将限制将建议单独纳入所有客户代码中的限制。

–吕克
19年1月9日在23:34



#11 楼

我认为客户端被黑客入侵的可能性高于服务器端。 (因为有一些IT专家照顾服务器)。如果您的计算机已经被黑客入侵。用来散列密码的客户端算法也可以被黑客窃取。尽快,您的算法不再是秘密。我认为,它变得无用了。

评论


我们通常不赞成使用秘密算法(请参阅Kerckhoffs的原理和“通过隐秘获得安全性”。密码散列当然不需要依赖此算法。至多我们应用密钥并希望攻击者即使设法窃取也无法找到它)数据库。

– CodesInChaos
2014年3月18日在11:03

在这种情况下,“服务器更安全”的说法毫无意义。 1)客户端知道明文密码,因此特洛伊木马可以使用键盘记录程序轻松窃取它。 2)密码哈希仅在服务器被黑客入侵并且数据库被盗时提供了优于纯文本密码的优势。

– CodesInChaos
2014年3月18日在11:05

丹科,CodesinChaos。您免费为我提供了有用的课程。

–李比利
2014年3月18日在11:14

Twitter的工作方式是,您关注那些您发现其推文有趣的人。无需征求许可。

– CodesInChaos
2014年3月18日在11:20

具有所有用户数据的服务器是比单个用户更具价值的目标。

–浓汤
2014年3月18日14:33