更改用户名时如何防止用户名和密码匹配?

信息安全 验证 密码 哈希 应用安全 密码策略
2021-08-27 22:09:50

假设我有一个系统,其中一项安全要求是阻止用户选择与其用户名匹配的密码。用户名不区分大小写,但密码是。服务器使用无法逆转的安全散列函数存储密码。

创建帐户时,用户名和密码最初都以明文形式提供给服务器进行比较。我们可以在内存中比较它们(不考虑大小写)以查看它们是否匹配,如果匹配,则指示用户选择不同的密码。一旦满足此检查,密码就会被安全地散列以进行存储,而用户名则以明文形式存储。在这里满足要求没有问题。

当用户想要更改他们的密码或正在为他们更改密码时,服务器可以检索他们的用户名记录并将其与新选择的密码值进行比较(再次忽略大小写)以查看它是否匹配。在这里满足要求也没有问题。

但是,系统也允许更改用户名。在此 ID 更改过程中,用户不必以明文形式向服务器提供密码。他们在进行身份验证时可能已经这样做了,但服务器不会将该密码以明文形式保存,以防万一他们决定更改用户名。因此,明文密码不可用于检查与新选择的用户名值是否匹配。

为了满足我们的要求,服务器可以使用相同的安全散列函数来散列新用户名并将其与记录的散列密码进行比较。如果它们匹配,则服务器可以指示用户选择不同的用户名。但是,由于用户名不区分大小写,因此当它可能为真时,此检查可能会失败。如果我提交“PwdRsch1”作为新的用户名选择并且我的密码是“pwdrsch1”,那么系统将允许它,因为哈希值不匹配。我——或者更糟糕的是,攻击者——随后可以使用匹配的用户名和密码“pwdrsch1”成功进行身份验证。

我们可以在散列和检查密码之前强制用户名小写,但是相反的情况是可能的。用户名将根据密码“PwdRsch1”检查为“pwdrsch1”并允许,因为它们不匹配。但后来我可以使用匹配的用户名和密码“PwdRsch1”成功进行身份验证。

我有哪些合理的选择来降低密码与不区分大小写的用户名匹配的风险?

4个回答

获得所需内容的唯一明智方法是在用户更改其用户名时询问密码。这样,服务器始终拥有在更改期间对用户名和密码进行准确比较所需的信息,并防止匹配。

由于敏感操作 - 例如更改密码,或者在您的情况下是用户名 - 无论如何都应该需要密码(以限制 XSS 的破坏),这应该不是问题。

您唯一的另一种选择是尝试所有可能的案例组合,对其进行哈希处理,并在用户更改其用户名时将其与存储的哈希值进行比较。

有点违背常规 -不要关心用户名是否更改为与密码“基本相似”的字符串。警告用户选择相同密码的危险并检查相同的匹配项。

无论您制定了多少规则,如果用户下定决心,他们就会找到绕过它们的方法。如果必须,请在更改用户名时提示输入密码,以便您可以强制它们使用相同的大小写,或者只是让它通过并在他们下次登录时检查并强制更改用户/密码。

唯一如果您的用户受到有针对性的攻击,那么这很重要。如果一个随机脚本小子(或其他一些投机者)获得了用户列表,他们有比尝试匹配用户名更复杂的工具来破解这些密码。就此而言,目标攻击者也是如此,但他们可能会从可以自己在键盘上键入的简单内容开始。如果是一个聪明的人试图破解密码“PwdRsch1”,你真的只是检查大小写差异就安全了吗?那么“pwdr5ch1”呢?“PwdRsch2”?“1hcsRdwP”?你可以为任何你能想到的场景编写规则,但要么你忘记了一个,要么你会很难选择用户名/密码组合,以至于他们只会使用“P4ssw0rd!”。

教育是让您的用户使用真正安全的密码的唯一方法,而且总会有不遵守的人。

假设用户名中有 10 个字母。那是 1024 种不同的大小写组合。全部检查。

不要存储小写密码哈希。1024 对您来说可能看起来很不方便,但对于攻击者来说,这是一天和三年之间的差异。

您应该强制用户 ID 和密码来自不同的集合。在评论中,用户 ID 必须遵循用户的法定名称,以一种公式化的方式“John Smith”->“jsmith”和“Jane Doe”->“jdoe”。然后,如果 Jane 与 John 结​​婚并取了他的名字,那么她的用户 id 必须更改为“jsmith2”之类的东西

因此,您可以规定密码中的第一个字符必须是符号,或者密码必须包含符号。

如果用户标识被截断为 8 个字符,您可能要求密码必须至少包含 9 个字符。

您可以将姓氏列表和给定名称列表的笛卡尔积用作密码黑名单。如果员工的姓名不在您的列表中,请将其添加,当人们更改密码时,问题就会自行解决。