Ozwel Asked: 2021-09-09 06:18:14 +0800 CST2021-09-09 06:18:14 +0800 CST 2021-09-09 06:18:14 +0800 CST 对于网站,您的密码哈希是在客户端还是服务器端计算的? 772 我想知道密码的输入是否在客户端/网络浏览器端或服务器端本地“转换”。 我很确定它在服务器端,但在这种情况下,它给我带来了一个担忧:这意味着您正在将密码发送给第三方。事实上,密码将通过安全通道传送到服务器,但最终服务器可以用它做任何事情。自己计算哈希并将其发送到服务器将使身份验证过程更加安全。 如果本地情况不可能,您能像我 5 岁那样解释为什么这是不可能的或一个好主意吗? passwords hashing 6 个回答 Voted Best Answer user1686 2021-09-09T06:31:54+08:002021-09-09T06:31:54+08:00 我想知道密码的输入是否在客户端/网络浏览器端或服务器端本地“转换”。 通常(使用常规的基于表单的登录)一切都在服务器端完成。 但在这种情况下,它给我带来了一个担忧:这意味着您正在将密码发送给第三方。事实上,密码将通过安全通道传送到服务器,但最终服务器可以用它做任何事情 是的,它可以。因此,对密码重用的警告。 自己计算哈希并将其发送到服务器将使身份验证过程更加安全。 就其本身而言——不,它不会。它将以一种风险换另一种风险。 使用服务器端散列,如果服务器的数据库泄漏(这种情况比 TLS MITM 更频繁地发生),除非被一一破解,否则这些散列几乎是无用的。使用客户端散列,攻击者可以简单地开始发送这些散列,就像它们是密码一样!现在攻击者可以登录每个人的帐户,而不是一次性的数据库泄漏,他们可以将这些哈希值留给自己,并在几个月或几年后使用它们登录。 (如果您让双方(第一个客户端,然后是服务器)对密码进行哈希处理,这仍然不会阻止恶意服务器存储客户端发送的哈希并将它们重新发送到其他地方,就像密码一样。) 要真正避免这两个问题,您需要的不仅仅是散列;你需要一个稍微复杂一点的协议(例如某种挑战/响应,它不会像“HTTP Digest”那样完全错误设计)。您还需要确保客户端发送的哈希不能在以后重用(甚至在不同的站点上),因为“重放攻击”是许多协议的问题。 例如,SCRAM 协议现在在 PostgreSQL 或 MongoDB 等非 Web 系统中有些普遍。然而,对于 Web 开发人员来说,所有这些都比仅仅制作 HTML 复杂得多<form>——它们需要自定义 JavaScript 代码,并且通常需要与服务器进行多步交互。 似乎“因为我们无论如何都在添加 JavaScript”,所以整个网络正在朝着根本不涉及密码的协议发展,例如使用公钥签名的 WebAuthn(有点像 SSH)。这并不一定意味着硬件加密狗和 2FA——“Windows Hello PIN”是操作系统提供的 WebAuthn 的一个示例。 Dmitry Grigoryev 2021-09-09T22:52:31+08:002021-09-09T22:52:31+08:00 自己计算哈希并将其发送到服务器将使身份验证过程更加安全 不,接受散列而不是密码会使该过程的安全性大大降低。这与保留纯文本密码相同:如果攻击者窃取了包含用户名和哈希值的服务器数据库,他们可以立即以任何用户身份登录! 散列的全部目的是迫使攻击者反转单向函数:从已知密码计算散列是微不足道的,找到与给定散列匹配的密码是困难的。当散列被盗时,像字典单词这样的差密码会受到损害,因为计算超过 100'000 个单词的散列很快。好的密码仍然是安全的,因为要计算哈希值,您需要先猜测密码。 LPChip 2021-09-09T06:24:17+08:002021-09-09T06:24:17+08:00 是的,当您在网站上输入密码时,它会以纯文本形式传输到服务器,然后服务器上的脚本可以对其进行任何操作,甚至可以将其存储为纯文本形式。为了保护用户(大多数国家/地区的法律要求网站),他们对密码进行哈希处理并仅存储哈希值,但这并不意味着它总是会发生。 但即便如此,如果密码散列被黑客入侵,如果真的需要并且手头有足够的时间(假设他们也获得了安全散列),它最终可能会被反转为普通密码。 那么这意味着什么,始终在每个站点上使用唯一的密码。最好使用带有随机密码生成器的密码管理器,这样您就可以记住一个密码而忘记其他密码。有基于云的解决方案,但也有本地解决方案,具体取决于您对云计算的不信任程度。 至于本地计算hash,技术上可以用javascript来做,但会带来巨大的安全风险。当您创建密码散列时,您使用该散列最终基于的唯一散列(安全散列)。因为这个唯一的散列在本地是未知的,所以无法解密密码。如果您进行本地散列,那么服务器必须首先向您发送秘密安全散列以获取散列密码。然后,黑客可以轻松解密任何散列。 Acccumulation 2021-09-09T21:25:57+08:002021-09-09T21:25:57+08:00 密码必须在服务器端进行哈希处理。如果您在服务器端的客户端上对密码进行哈希处理并将哈希密码发送到服务器,那么哈希密码是服务器检查以验证您的东西,而“服务器检查以验证您的东西”根据定义是,密码。所以根据定义,你发送给服务器的东西就是密码。如果您发送的东西是通过散列生成的,那么您正在无缘无故地做一堆额外的工作。更重要的是,用您的密码服务器端的哈希替换您的密码是没有用的,因为它不会改变“如果有人入侵服务器,他们将拥有可以让他们登录到您的帐户的数据”的威胁向量”。关键是服务器没有允许身份验证的信息; 事实上,密码将通过安全通道传送到服务器,但最终服务器可以用它做任何事情。 嗯……是吗?不可能创建一个安全系统来防止“运行服务器的人正在做他们不应该做的事情”的威胁向量。 自己计算哈希并将其发送到服务器将使身份验证过程更加安全。 不,因为正如我解释的那样,这意味着您发送的实际上是您的密码。也就是说,您发送的内容如果被拦截,将允许您免费访问您的帐户。发送散列版本和未散列版本都不会解决该威胁向量。无论哪种方式,任何可以阅读流量的人都可以冒充您。 要解决此问题,您需要进一步的安全协议,例如通过加密通道进行通信,并要求所有消息包含随机生成的盐,该盐会随会话而变化。 Nolonar 2021-09-11T07:36:36+08:002021-09-11T07:36:36+08:00 如果本地情况不可能,您能像我 5 岁那样解释为什么这是不可能的或一个好主意吗? 永远不要相信客户 只要有足够的时间和精力,用户就可以修改任何客户端。 假设我是一名黑客。 我刚刚破解了superuser.com数据库,现在我有一个很长的用户名和密码列表。 除了密码是散列的,所以我实际上不能使用它们。 但是密码没有在服务器上散列,它们在我的浏览器上散列。 所以我需要做的就是修改 JavaScript 登录脚本以删除散列过程。 而且我已经知道所有的哈希值了。 如您所见,在客户端对密码进行哈希处理会使整个哈希处理过程本身毫无用处。 相比之下,如果在服务器上处理散列,整个故事将发生巨大变化: 密码在服务器上进行了哈希处理,所以我实际上需要知道密码。 如果我可以绕过服务器上的散列过程,我什至不需要首先窃取密码;我只能强迫服务器让我进去。 所以现在我需要花费大量的时间和精力来找到一个哈希值与我窃取的哈希值相匹配的密码。 这就是为什么哈希总是在服务器端完成,而不是在客户端。这也是我们“从不相信客户”的原因。 Micah Zoltu 2022-09-29T00:13:09+08:002022-09-29T00:13:09+08:00 TL;博士 您应该在客户端和服务器端都对密码进行哈希处理。输入到密码输入框中的密码在散列之前应仅暂时存在于内存中,并应在散列完成后尽快删除。 客户端散列 如果用户重复使用密码,但它在客户端使用特定于该网站的盐进行哈希处理,那么如果攻击者能够读取发送到服务器的流量,他们只能访问他们已经破坏流量的网站至。 值得注意的是,如果攻击者有能力写入发送给客户端的数据,那么他们可以更改客户端,使密码直接以明文形式发送给攻击者。客户端散列仅保护对从客户端到服务器的数据具有读取权限但对从服务器到客户端的数据没有写入权限的人。 服务器端哈希 当服务器在存储/检查密码之前对其进行哈希处理时,可以保护用户免受获得数据库读取访问权限的攻击者的攻击。可以读取数据库的攻击者只会看到密码的哈希值,但他们不会知道该哈希值的原像,因此他们无法通过服务器进行身份验证。 值得注意的是,如果攻击者对数据库有写访问权限,可以读取身份验证应用程序的内存,或者可以执行服务器端代码,那么这种保护就没有帮助,因为攻击者可以在密码被散列之前拦截密码服务器。但是,只有在攻击者拥有此访问权限时进行身份验证的用户才有风险。 两者都做 一个设计良好且关心用户安全的应用程序应该实施深度防御策略,您可以在客户端和服务器上进行哈希处理,从而保护用户免受各种攻击。服务器端哈希比客户端哈希更常见,因为对数据库的读取访问似乎是一种更常见的妥协,但这并不意味着您应该忽略获得对网络流量的读取访问权限的 MITM 攻击。
通常(使用常规的基于表单的登录)一切都在服务器端完成。
是的,它可以。因此,对密码重用的警告。
就其本身而言——不,它不会。它将以一种风险换另一种风险。
使用服务器端散列,如果服务器的数据库泄漏(这种情况比 TLS MITM 更频繁地发生),除非被一一破解,否则这些散列几乎是无用的。使用客户端散列,攻击者可以简单地开始发送这些散列,就像它们是密码一样!现在攻击者可以登录每个人的帐户,而不是一次性的数据库泄漏,他们可以将这些哈希值留给自己,并在几个月或几年后使用它们登录。
(如果您让双方(第一个客户端,然后是服务器)对密码进行哈希处理,这仍然不会阻止恶意服务器存储客户端发送的哈希并将它们重新发送到其他地方,就像密码一样。)
要真正避免这两个问题,您需要的不仅仅是散列;你需要一个稍微复杂一点的协议(例如某种挑战/响应,它不会像“HTTP Digest”那样完全错误设计)。您还需要确保客户端发送的哈希不能在以后重用(甚至在不同的站点上),因为“重放攻击”是许多协议的问题。
例如,SCRAM 协议现在在 PostgreSQL 或 MongoDB 等非 Web 系统中有些普遍。然而,对于 Web 开发人员来说,所有这些都比仅仅制作 HTML 复杂得多
<form>
——它们需要自定义 JavaScript 代码,并且通常需要与服务器进行多步交互。似乎“因为我们无论如何都在添加 JavaScript”,所以整个网络正在朝着根本不涉及密码的协议发展,例如使用公钥签名的 WebAuthn(有点像 SSH)。这并不一定意味着硬件加密狗和 2FA——“Windows Hello PIN”是操作系统提供的 WebAuthn 的一个示例。
不,接受散列而不是密码会使该过程的安全性大大降低。这与保留纯文本密码相同:如果攻击者窃取了包含用户名和哈希值的服务器数据库,他们可以立即以任何用户身份登录!
散列的全部目的是迫使攻击者反转单向函数:从已知密码计算散列是微不足道的,找到与给定散列匹配的密码是困难的。当散列被盗时,像字典单词这样的差密码会受到损害,因为计算超过 100'000 个单词的散列很快。好的密码仍然是安全的,因为要计算哈希值,您需要先猜测密码。
是的,当您在网站上输入密码时,它会以纯文本形式传输到服务器,然后服务器上的脚本可以对其进行任何操作,甚至可以将其存储为纯文本形式。为了保护用户(大多数国家/地区的法律要求网站),他们对密码进行哈希处理并仅存储哈希值,但这并不意味着它总是会发生。
但即便如此,如果密码散列被黑客入侵,如果真的需要并且手头有足够的时间(假设他们也获得了安全散列),它最终可能会被反转为普通密码。
那么这意味着什么,始终在每个站点上使用唯一的密码。最好使用带有随机密码生成器的密码管理器,这样您就可以记住一个密码而忘记其他密码。有基于云的解决方案,但也有本地解决方案,具体取决于您对云计算的不信任程度。
至于本地计算hash,技术上可以用javascript来做,但会带来巨大的安全风险。当您创建密码散列时,您使用该散列最终基于的唯一散列(安全散列)。因为这个唯一的散列在本地是未知的,所以无法解密密码。如果您进行本地散列,那么服务器必须首先向您发送秘密安全散列以获取散列密码。然后,黑客可以轻松解密任何散列。
密码必须在服务器端进行哈希处理。如果您在服务器端的客户端上对密码进行哈希处理并将哈希密码发送到服务器,那么哈希密码是服务器检查以验证您的东西,而“服务器检查以验证您的东西”根据定义是,密码。所以根据定义,你发送给服务器的东西就是密码。如果您发送的东西是通过散列生成的,那么您正在无缘无故地做一堆额外的工作。更重要的是,用您的密码服务器端的哈希替换您的密码是没有用的,因为它不会改变“如果有人入侵服务器,他们将拥有可以让他们登录到您的帐户的数据”的威胁向量”。关键是服务器没有允许身份验证的信息;
嗯……是吗?不可能创建一个安全系统来防止“运行服务器的人正在做他们不应该做的事情”的威胁向量。
不,因为正如我解释的那样,这意味着您发送的实际上是您的密码。也就是说,您发送的内容如果被拦截,将允许您免费访问您的帐户。发送散列版本和未散列版本都不会解决该威胁向量。无论哪种方式,任何可以阅读流量的人都可以冒充您。
要解决此问题,您需要进一步的安全协议,例如通过加密通道进行通信,并要求所有消息包含随机生成的盐,该盐会随会话而变化。
永远不要相信客户
只要有足够的时间和精力,用户就可以修改任何客户端。
假设我是一名黑客。
我刚刚破解了superuser.com数据库,现在我有一个很长的用户名和密码列表。
除了密码是散列的,所以我实际上不能使用它们。
但是密码没有在服务器上散列,它们在我的浏览器上散列。
所以我需要做的就是修改 JavaScript 登录脚本以删除散列过程。
而且我已经知道所有的哈希值了。
如您所见,在客户端对密码进行哈希处理会使整个哈希处理过程本身毫无用处。
相比之下,如果在服务器上处理散列,整个故事将发生巨大变化:
密码在服务器上进行了哈希处理,所以我实际上需要知道密码。
如果我可以绕过服务器上的散列过程,我什至不需要首先窃取密码;我只能强迫服务器让我进去。
所以现在我需要花费大量的时间和精力来找到一个哈希值与我窃取的哈希值相匹配的密码。
这就是为什么哈希总是在服务器端完成,而不是在客户端。这也是我们“从不相信客户”的原因。
TL;博士
您应该在客户端和服务器端都对密码进行哈希处理。输入到密码输入框中的密码在散列之前应仅暂时存在于内存中,并应在散列完成后尽快删除。
客户端散列
如果用户重复使用密码,但它在客户端使用特定于该网站的盐进行哈希处理,那么如果攻击者能够读取发送到服务器的流量,他们只能访问他们已经破坏流量的网站至。
值得注意的是,如果攻击者有能力写入发送给客户端的数据,那么他们可以更改客户端,使密码直接以明文形式发送给攻击者。客户端散列仅保护对从客户端到服务器的数据具有读取权限但对从服务器到客户端的数据没有写入权限的人。
服务器端哈希
当服务器在存储/检查密码之前对其进行哈希处理时,可以保护用户免受获得数据库读取访问权限的攻击者的攻击。可以读取数据库的攻击者只会看到密码的哈希值,但他们不会知道该哈希值的原像,因此他们无法通过服务器进行身份验证。
值得注意的是,如果攻击者对数据库有写访问权限,可以读取身份验证应用程序的内存,或者可以执行服务器端代码,那么这种保护就没有帮助,因为攻击者可以在密码被散列之前拦截密码服务器。但是,只有在攻击者拥有此访问权限时进行身份验证的用户才有风险。
两者都做
一个设计良好且关心用户安全的应用程序应该实施深度防御策略,您可以在客户端和服务器上进行哈希处理,从而保护用户免受各种攻击。服务器端哈希比客户端哈希更常见,因为对数据库的读取访问似乎是一种更常见的妥协,但这并不意味着您应该忽略获得对网络流量的读取访问权限的 MITM 攻击。