9

嘿,首先,让我说,我不是在询问 md5(md5(... 之类的东西,已经有关于它的主题。

我的问题是这样的:

我们允许我们的客户在本地存储他们的密码。自然,我们不希望它们存储在计划文本中,因此我们在存储和/或发送之前在本地对它们进行 hmac 处理。现在,这很好,但如果这就是我们所做的一切,那么服务器将拥有存储的 hmac,并且由于客户端只需要发送 hmac,而不是纯文本密码,攻击者可以使用来自服务器的存储哈希访问任何人的帐户(当然,在灾难性的情况下,有人会获得对数据库的这种访问权限)。

因此,我们的想法是通过 hmac 对客户端上的密码进行一次编码,将其发送到服务器,然后通过 hmac 对其进行第二次编码,并将其与存储的两次 hmac 化密码进行匹配。这将确保:

  • 客户端可以将密码存储在本地,而无需将其存储为纯文本
  • 客户端可以发送密码而不必(过多)担心其他网络方
  • 服务器可以存储密码,而不必担心有人从服务器窃取密码并使用它进行登录。

自然,所有其他事情(强密码、双盐等)也适用,但与问题并不真正相关。

实际的问题是:这听起来像一个可靠的安全设计吗?我们是否忽略了以这种方式做事的任何缺陷?可能有这样的安全模式吗?

附录:我们不想在客户端以纯文本形式本地存储密码的原因是因为令人遗憾的是,许多人仍然对多个服务使用相同的密码,因此获得“真实”密码会更大用户的安全漏洞,而不是让他的哈希被盗。

4

7 回答 7

12

我跑出了门,但飞碟发出了砰砰声,你不要惹到飞碟。

您正在做的是用另一个常量值替换密码。您在这里一无所获,您拥有的唯一安全性是无法在客户端计算机上发现纯文本密码。

然后您似乎要做的是将密码的 HMAC(您确定您的意思是 HMAC?如果是,密钥来自哪里并存储在哪里?)作为密码本身 - 您将其从客户端发送到服务器它用于身份验证。第二个 HMAC 或散列是没有意义的 - 您正在与发送的值进行比较 - 它是任何其他名称的密码。因此,作为攻击者,我不需要窃取密码,只需窃取存储在客户端计算机上的 HMAC。这里一无所获。

于 2010-06-10T20:43:57.183 回答
7

警告:我不是安全专家。我会 ping blowdart看看他是否愿意加入。

如果客户端只是存储散列,并且基于散列有效地传输某些东西,那么他们实际上是以纯文本形式存储它。第一个散列提供的唯一好处是,如果他们在不同的系统上使用了相同的密码,那么如果散列被泄露,其他系统就不会受到损害。

换句话说:如果有人可以掌握存储在服务器上的哈希值,这就是他们登录系统所需要的一切......就像纯文本存储一样。

于 2010-06-10T20:28:40.633 回答
6

正如其他人所说,将客户端和您的系统隔离开来,这并不能真正给您带来任何好处——第一个哈希只是成为密码。

如果(很可能)客户端在其他系统上使用相同的密码,则该值出现。在这种情况下,如果客户端计算机受到威胁,那么至少您的哈希密码的本地副本不允许攻击者访问其他系统。显然,客户端的攻击者现在将能够访问您的服务器 - 毕竟,他们已经获得了密码。

有权访问服务器上的双哈希值的攻击者不会向他们购买任何东西,因为他们无法将其反转以获取单个哈希(即“密码”)。当然,如果攻击者能够读取您的安全数据库,那么我怀疑他们还有其他可用的攻击媒介 :)

此外,正如另一位海报所说,确保在两个哈希上都使用盐。如果不这样做,如果密码不强,则反转哈希实际上可能非常简单。

编辑 - 实际上,考虑一下,因为您使用哈希作为密码,所以您实际上不需要在服务器上使用盐。没有人能够创建一个有效的彩虹表 :) 但是客户端仍然需要一个。

于 2010-06-10T20:36:40.633 回答
3

不,这不安全。散列值实际上是密码。密码来源于用户认为是密码的其他东西这一事实并不重要。这是一个对用户进行身份验证的秘密值,对吧?对我来说听起来像是密码。

我认为这取决于声明,“当然,我们不希望它们存储在计划文本中,所以我们在存储和/或发送之前在本地对它们进行 hmac 处理。” 如果系统被更改,使得哈希密码现在具有与密码曾经相同的权力,则应该对哈希密码使用相同级别的谨慎。

于 2010-06-10T20:31:29.643 回答
1

吹镖一针见血-您只是将秘密更改为偷窃,而不是保护任何东西。你试图复制的是一个旧的身份验证协议,我一辈子都记不住它的名字。以下是它的工作原理:

初始化时,服务器会获取您的密码,迭代地散列 n 次,用 F n (pass) 表示。客户端有密码和数字 n。

你去验证,然后发送给服务器 F n-1(pass)——也就是密码散列 n-1 次。服务器再对其进行一次散列,将其与 F n(通过)进行比较,如果它们匹配,您就可以访问。然后服务器将 F n(通过)替换为 F n-1(通过),然后您将 n 递减。

下次您进行身份验证时,您发送 F n-2(通过)并重复该过程。

让我们检查一下安全性:

  • MITM:协议中没有内置抵抗力,您必须将其分层在 SSL 中
  • 重放攻击:它们不起作用,因为服务器已经减少了哈希迭代。
  • 窃听:下一次认证将使用 F n-1(通过)完成。你有 F n(通过)。根据散列函数的定义,从 F n (pass) 到 F n-1 (pass) 是不可行的
  • 拥有服务器:您不知道客户端的密码,也无法以他们的身份进行身份验证,因为当您只有 F n时,您再次需要 F n-1 (通过)
  • 拥有客户端:由于您存储了 F n-1(pass)(因此他们不必输入 pass) - 那么拥有客户端将使攻击者登录。如果您只存储 n 而不是密码,这将被阻止,但您显然希望保存密码。

这就是你想要完成的。然而,这个协议没有被使用是有原因的——它是一个要同步的大婊子。如果客户端和服务器由于半完成的步骤而失去同步,您将被锁定。您为避免这种情况而内置的任何弹性都可能会降低重放或窃听的安全性。

于 2010-06-10T21:54:22.960 回答
0

我不确定这会给您带来什么,而不是在本地以明文形式存储密码。

本地加密的目的是防止黑客将密码发送到您的服务器。但是,如果您要发送加密的表格……好吧,您什么都没买。

相反,本地计算机应以双向加密格式存储密码。这意味着它可以被解密。您在传输之前执行的操作。db 可以存储单向加密格式(即使使用单独的加密机制)。在比较之前,您对收到的内容进行加密然后检查。

于 2010-06-10T20:29:11.727 回答
0

旨在实现的密码的初始散列是什么?它将防止发现密码的纯文本版本。它不会阻止使用该哈希值来计算双重哈希值。

于 2010-06-10T20:29:28.350 回答