因此,流量被加密到网站,因此密码在传输过程中是安全的,而且如果网站被黑客入侵,那么数据库只包含哈希值。
但是黑客不能创建一个服务器端脚本来将用于登录网站的用户名和密码存储在一个文件中,因为它们已被解密并且尚未散列?这不会让每个用户都知道,但它会允许他们查看在站点受到攻击时尝试登录该站点的用户密码。
在客户端散列密码不是更好吗?
因此,流量被加密到网站,因此密码在传输过程中是安全的,而且如果网站被黑客入侵,那么数据库只包含哈希值。
但是黑客不能创建一个服务器端脚本来将用于登录网站的用户名和密码存储在一个文件中,因为它们已被解密并且尚未散列?这不会让每个用户都知道,但它会允许他们查看在站点受到攻击时尝试登录该站点的用户密码。
在客户端散列密码不是更好吗?
你提到的弱点是真实的。重要的一点是,一旦服务器被入侵,攻击者就没有动力去获取授予对该服务器访问权限的密码——他已经在这个地方了。但是,人类用户有重用密码的习惯,这是一个大问题,因为重用密码意味着一台服务器上的妥协往往会“传播”,正如您解释的那样:攻击者获取用户U的密码P,并猜测(唉,大多数时候是正确的)同一用户U将在其他一些服务器上使用相同的密码。
散列客户端是一个好主意,但有一些细节:
无论客户端向服务器发送什么,无论是密码本身还是散列密码,都会授予访问权限。它与密码等效。如果服务器将这些哈希“按原样”存储在其数据库中,那么它与存储明文密码的服务器处于相同的情况,这很糟糕。因此,服务器也必须做一些散列。
仅当客户端上有执行散列的代码时,才会发生客户端散列。在 Web 上下文中,这意味着 JavaScript。不幸的是,JavaScript 在加密实现方面很差。特别是,它非常慢,因此客户端散列将无法使用良好的密码散列通常需要的许多迭代(有关详细信息,请参阅this)。此外,这不适用于没有 JavaScript 的客户端。
仍然在 Web 上下文中,客户端散列(如果发生)是由服务器发送的JavaScript 代码完成的。如果服务器受到恶意控制,那么它可能会发送恶意 JavaScript,假装进行哈希处理,但实际上并没有。用户不会更聪明。因此,根本问题没有解决。
客户端散列通常以“服务器救济”的名义设想,不是为了提高对恶意服务器的安全性,而是允许服务器处理许多并发用户,而不会将其所有 CPU 用于大量散列。JavaScript 就是这样,现在这并不常见。
所以这有两个独立的部分。
首先,服务器受到威胁,其次,向服务器发送哈希而不是密码。
对于服务器受到威胁的第一部分,是的,攻击者几乎可以为所欲为。如果他们拥有服务器,他们确实可以从传递给服务器的用户那里获取用户名和密码。这就是为什么需要强化服务器以抵御攻击并定期更新,以便它们提供尽可能少的攻击面。
对于第二部分,如果您让客户端预先计算哈希,那么该哈希实际上已成为密码。如果攻击者窃取了哈希数据库(但没有破坏 Web 服务器),他不需要找到变成这些哈希的密码;他只需将哈希发送到 Web 服务器,它就会进行身份验证,因为服务器已经期望哈希作为输入来与它的数据库进行比较。
如果您的服务器完全拥有,您可能无法阻止对发送给客户端执行的代码进行简单的服务器端修改。
但是,如果这是具有不同客户端和服务器组件的预安装或预分发软件包的一部分(这可能包括具有下载组件且驻留在客户端操作系统上的 Web 应用程序),则客户端哈希在某种意义上可能很有用,虽然攻击者可能仍然可以使用这些哈希对您的数据库进行身份验证(或者只是重置密码,如评论之一中所述),但他们不再能够轻松访问将发送到您的服务器的明文密码(通过 SSL)用于加盐哈希和数据库存储。
因此,如果您有一个客户端在多个地方使用相同的密码,只要哈希不是一般可逆的,您的特定服务器妥协就不再泄露攻击者可以在其他地方使用的凭据。这将通过随机客户端加盐得到增强(这样您就不会得到相同算法总是为该明文生成的相同哈希值)。
我发现很多人(尤其是在 PHP 领域)误解了散列的作用。这是方法论
$2y
散列(BCRYPT),成本和盐存储在同一个字符串中。因此,使用相同的成本和盐,服务器使用用户提供的密码生成哈希(请记住,哈希在设计上是单向的)假设有人入侵了您的服务器,您的用户会得到更好的保护,因为每个散列的盐是随机的。因此,您将不得不分别暴力破解每个密码(任何类型的安全性背后的核心理论是将做某事的成本提高到有人不会尝试的程度)。以前流行的散列系统 SHA1 和 MD5 几乎总是在没有任何盐的情况下生成,这使得它们不仅容易受到散列本身的任何弱点的影响,而且还容易受到彩虹表攻击(没有盐,每个 SHA1 和 MD5 对于给定的字符串都是相同的) .
真的没有办法做这个客户端,因为