客户端散列可以提高事后安全性以应对密码泄露吗?

信息安全 哈希 客户端
2021-08-24 13:39:32

该站点上的几个问题涉及客户端密码散列,除了保护用户可能使用相同密码的其他站点之外,它们都没有承认任何安全优势。

然而,似乎有一种情况没有得到解决,我觉得客户端散列可以提高事后的安全性,防止某些泄漏 - 特别是 Heartbleed。对此类错误的最佳反应确实是更改密码,但用户犹豫不决,网站几乎从不希望要求它。

想象一下哈希是这样的。

  • 客户端有一个纯文本密码。
  • 这被散列到H0然后到H1
  • 这被发送到服务器,服务器将其散列到H2,存储在数据库中。

然后假设发生了 Heartbleed,或者某个黑客将代码注入哈希器以通过电子邮件将H1发送给自己,或者发生任何其他安全错误,在一段时间内完全危及服务器(但不是客户端)。该漏洞被发现并修复,但所有H1哈希值都被视为已泄露。

比方说,就像经验表明的那样,出于商业原因,重置每个人的密码不是可接受的响应。

使用这种方法,可以解决此问题。

  • 修补客户端现在发送(和服务器现在需要)哈希H0
  • H0成为新密码。
  • H0对黑客来说是未知的,但仍然可以被服务器验证。
  • 如果需要,可以从H0生成备用哈希H1'以替换H1

显然,这仍然足以让攻击者进行本地暴力攻击,因此它不是完全治愈的方法。然而,泄露纯文本密码似乎更可取,特别是如果用户不愿意更新它或充其量将其替换为"${old_password}2".

我对安全知之甚少,所以我可能错过了一些重要的警告。想法?

3个回答

散列客户端和服务器端对服务器端进行两次散列没有理论上的好处;除非客户端和服务器之间的连接不可信。

然而在实践中,我看到了多个纯文本密码最终出现在日志中的实例(主要是错误日志)。在这种特殊情况下,它具有明显的优势。

我相信您可以使用每个密码唯一的盐来从 H0 散列到 H1。

一旦 H1 被破坏,因为服务器知道这个特定的 Salt,客户端可以通过发送 H0 进行身份验证,然后服务器可以检查 H0 + Salt => H1。然后服务器可以将 Salt 更改为 Salt' 并将 H0 + Salt' => H1' 注册为新密码。

我认为这是可能的,但我建议不要这样做:复杂性是安全的敌人。

某些身份验证协议会在传输之前对密码进行散列处理,最值得注意的是WAP/WPA2 PSK 四向握手在这种场景下,WPA协议需要防止伪装攻击,使得流氓AP在提示客户端认证时无法获取明文密码。

在该协议中,已经获得的攻击者H1 = hash(H0)可以使用该值进行身份验证,而无需知道明文密码。这违反了CWE-294: Authorization bypass by capture replayhash(hash'(H0))此外,由于不使用密码盐(CWE-759),因此计算密码哈希存在问题,因此预计算攻击构成了“最短的妥协路径”。

如果实施得当,基于零知识密码证明的身份验证系统会显着降低内存泄露攻击(例如心脏出血、日志泄露漏洞和 MITM 的某些方面)造成的影响。但是,基于字典的密码破解或多或少不受影响。

我认为你计划中的缺陷是你的陈述

H0 对黑客来说是未知的,但仍然可以被服务器验证。

不是这种情况。请记住,哈希是一种方式。服务器从您那里收到的所有信息都是 H1,它们已将其转换为 H2(现在已被入侵)。服务器不知道生成 H1(即 H0)的输入是什么。此外,假设服务器只保留了 H2 而没有保留 H1。如果他们保留了 H1,那么是的,他们可以拥有 H0 并与 H1 进行比较,但他们保留了 H2。

如果您考虑一下,虽然 H1 是您最初发送到服务器的内容,但从服务器的角度来看,它只是一个密码 - 一个可能很长的密码,但仍然只是一个密码。然后,服务器需要对该密码进行哈希处理以存储它(创建 H2)。我们也希望服务器没有 H1 的记录。当您进行身份验证时,您发送 H1,服务器对其进行哈希处理以获取 H2。为了使您的方案正常工作,服务器还需要保留 H1,这就像保留纯文本密码一样。一旦黑客掌握了 H1 哈希数据库,他们就可以以与该哈希关联的用户身份访问服务器,而无需执行任何其他操作。

另一个稍微掩盖了您可能需要更多思考的部分建议是

修补客户端现在发送(和服务器现在需要)哈希 H0。

这是一个潜在的问题,或者至少可能与更改密码一样多。如果您要自动允许这种路径,从而减少/避免用户采取行动的需要,那么您将打开另一个潜在的安全问题 - 如何/谁将启动该修补程序以及您将如何防止未经授权的修补程序。如果您希望用户进行修补,则可能需要花费更多的努力才能做到正确,而不仅仅是让他们更改密码。

编辑:正如评论中所指出的,您可以通过将 H0 哈希两次 H0 -> H1 -> H2 并与服务器拥有的 H2 进行比较来验证 H0 哈希。所以也许等式的那一部分可能会起作用。

然而,从使用 H1 到使用 H0 的修补或协调仍然是 IMO 的问题。“正常”更新/补丁机制将不起作用,因为此类机制依赖于单一信任“事实来源”。例如,如果您在 Windows 上信任 Windows 更新服务,如果您在 OSX 上信任 OSX 更新服务。但就网站而言,我们正在处理分散的基础设施。

考虑一个环境,该方案已被所有 Web 服务器的全部或部分子集采用。如果 Web 服务器受到攻击,那么该服务器有必要以某种方式通知客户端他们现在需要发送 H0 而不是 H1。此时,事情开始变得非常复杂,复杂性是安全的天敌。

您不能在全局范围内进行更改,即现在要求所有使用此方案的站点使用 H0 而不是 H1,因为这会导致协调问题 - 您需要以某种方式告诉所有使用该方案的服务器切换到 H0 -> H1 -> h2 方法。现在您必须更新服务器和客户端并协调该更改,否则某些站点将停止工作。

因此,您需要在每个站点的基础上执行此操作。这意味着您需要在您的方案中内置一些机制,允许服务器告诉客户端它想要哪个哈希进行身份验证 - H0 或 H1。现在你有另一个问题。您如何防范要求 H0 的流氓服务器?

鉴于任何密码方案的最大问题之一是人们倾向于在多个站点上使用相同的密码。我们知道这是不好的做法,但人们还是会这样做。如果你要访问一个坏的服务器,它可能会要求 H0。现在该服务器具有 H0 并且可以对其进行哈希处理以获取 H1 并使用该哈希来访问您可能使用的其他服务器,这些服务器仍然依赖原始 H1 作为密码。这甚至可能是对受感染主机的另一个攻击向量的一部分——一旦你破坏了一个主机,你就可以开始询问 H0 哈希值。

这里真正的问题是我们正在增加额外的复杂性,这将增加无法预料的“漏洞”,这只会增加最小可能的额外安全性,并且无法修复使用密码保护访问的基本(并且可能无法修复)方法 - 底线是密码他们自己的访问控制从根本上被破坏了。真正需要的是一种方便的方法,可以在身份验证过程中添加额外的因素,并摆脱依赖简单密码的方法