如何安全地检查用户名是否存在?

信息安全 Web应用程序 密码管理
2021-09-06 17:29:09

我正在开发我的网络应用程序的入职功能,并且在某些时候我要求新用户选择一个用户名。

当用户到达这一点时,我有他/她的电子邮件和一个通过 SMS 验证的手机号码,并且他/她已经通过了 Google 的 no CAPTCHA reCAPTCHA。

我需要检查用户选择的用户名是否已经存在,如果存在,则提示用户选择另一个用户名。

在浏览网页时,我遇到了一些页面,说实现此类功能还为攻击者提供了一个工具来检查用户名是否存在。

检查用户名是否存在的最佳做法是什么?

4个回答

该消息来源说,在这种情况下避免用户枚举几乎是不可能的,并且延迟攻击者是您能做的最好的事情:

如果您是开发人员,您可能想知道如何保护您的网站免受此类攻击。好吧,尽管几乎不可能使帐户注册工具不受用户名枚举的影响,但是可以通过实施 CAPTCHA 机制来避免针对它的自动用户名枚举攻击。

但是,我可能错过了一些东西——我也很好奇其他人是否有更好的解决方案。

允许多个用户拥有相同用户名的替代方案要糟糕得多!

该系统真的会发生什么

  • 用户请求新密码
  • 您现在必须检查密码以确保不会发生冲突
  • 用户可以使用它来暴力破解其他帐户

那很糟。因此,您需要防止多个用户拥有相同的用户名。你通过检查来做到这一点。


如果用户可以找到另一个用户的用户名会发生什么

这是您所看到的场景,以及如何防止有人恶意使用它。你在这里冒什么风险?

  • 用户可以找到用户名
  • 仍然不提供访问权限,因为他们现在必须猜测密码

好的,这提供了更多的安全性,并且仍然可以防止用户的电子邮件和其他敏感信息泄露。但现在您想尝试减轻攻击。你是怎样做的?

减轻注册攻击

这里有几种技术可以防止它,但到目前为止最好的是速率限制和通过 IP 记录的最大尝试。

速率限制、最大尝试次数和 IP 记录

当用户尝试注册时,他们只能如此快速地检查可用用户名。实际上,一个真实的人需要一两秒钟才能输入一个新的用户名。这使您可以进行一些简单的制衡然而,这只有在他们尝试注册时才会真正发生。当用户攻击您并使用未注册的用户名时,所发生的一切就是他们已经注册了该用户名。那好吧。现在他们必须重新开始注册过程,您可以在这里查看。

  • 用户尝试非常快地注册很多帐户:一个机器人,阻止它们并将它们踢出(速率限制)
  • 用户尝试了很多:用手攻击,将他们踢出去(最大尝试次数)
  • 用户回来了:相同的 IP 地址表明攻击者非常坚定。禁止他们的 IP(最多重复尝试)

现在攻击者已经暴露了自己并在 IP 级别被禁止。你知道这里发生了一些不好的事情,有一个可能已经闪现的用户名日志,最好还没有个人信息泄露。很好!

但是,现在您需要返回并注销所有为尝试查找其他帐户而创建的帐户。幸好你有这些日志!


没有电子邮件的用户名的衰落

当您不将帐户绑定到电子邮件时,您需要注意一个大缺陷:用户名可以预先注册并持有赎金那么证明用户名的所有权是非常困难的。这让我们有人对您的系统进行不同类型的攻击,他们只是试图预先注册很多人的帐户并勒索他们的赎金。希望您有上述检查的日志,以便您可以尝试在行动中抓住它们。


备择方案

您提到他们已经完成了电子邮件确认过程,因此此时处理它的另一种方法是将其链接到电子邮件。注册后,如果他们想更改电子邮件,则必须登录,然后发送带有电子邮件链接的请求以进行更改。这可以使用时间敏感令牌来完成。现在他们也可以有一个用户名来显示在网站上。由于显示名称可能重叠并且无法尝试使用该信息访问另一个帐户,因此此处的陷阱也得到了缓解,但电子邮件提供了对真实性的检查(可能还有某种物理标识符,如个人资料图片)

问题 当用户尝试登录时,他或她输入了他们的用户名。注册时,您会被告知是否使用了用户名。如果你找到一个被盗用的用户名,你可以尝试用它登录并可能破解它。

解决方案 1(引入了另一个问题):
如果用户必须使用电子邮件登录,那么知道是否使用了用户名将无济于事。您使用电子邮件登录,而不是用户名。因此,当您知道helloman有用户名时,攻击者无法知道在登录表单中输入什么内容。但是,现在的问题是告诉用户是否接收了电子邮件。

如何通过电子邮件确认进行保护
注册时,不要告诉用户电子邮件是否被占用。相反,告诉他们已发送确认电子邮件。向他们发送电子邮件,如果该电子邮件之前已注册,请发送一封电子邮件,说明 1)他们的帐户已经存在,以及 2)有人试图注册他们的电子邮件。向用户保证他们的帐户是安全的。

如果尝试注册helloman@example.com的人不是真正的 helloman,那么他们可能不会看到 helloman 的电子邮件收件箱。如果真正的 helloman 尝试使用已注册的电子邮件创建一个新帐户,那么他们将收到一封电子邮件,说明他们已经注册了一个帐户。这种方法的主要问题是,如果黑客设法破解了 helloman@example.com。但是,当今最常见的电子邮件系统非常安全,因此不必担心。此外,如果他们的帐户被黑客入侵,这不是您的问题。

允许用户(或攻击者)找出用户名是否存在被称为“用户名枚举”漏洞。这里总结得很好

作为攻击者,如果我可以使用您的登录或忘记密码页面将我的列表从 10000 个目标缩小到 1000 个目标,我会的。

您可以将“注册页面”添加到该列表中。这有助于攻击者进行任何网络钓鱼活动或任何密码猜测攻击。如果 Bob 的妻子 Alice 可以在 Ashley Madison.com 上找到 bob@example.com 是否存在,这也是一个隐私问题。

基本上,如果您允许用户选择与他们的电子邮件分开的自己的用户名,那么为了防止用户枚举,您应该只允许使用电子邮件/密码登录,并简单地使用用户名作为识别网站上其他用户的一种方式。

这样说对不起,用户名foob​​ar被占用,请选择另一个没有漏洞。

这是因为与电子邮件地址不同,这些用户名在世界上不会是全球唯一的。因此,当您说一个被占用时,不会侵犯用户隐私。另外,由于您不能直接使用用户名登录,因此不会产生用户枚举漏洞。

作为额外的奖励,这也使帐户恢复和注册过程更加简单(这总是有利于安全)。也就是说,不需要“忘记用户名”功能和“忘记密码”功能——因为他们使用他们会记住的电子邮件地址登录,这是他们唯一需要重新获得访问权限的事情,前提是他们仍然可以访问他们的电子邮件帐户。确保您阻止用户枚举您的电子邮件地址 - 请参阅此答案

作为对此答案的更新,我注意到您说您不想使用电子邮件作为用户名,以防用户决定更改其电子邮件地址。如果在您的体系结构中使用“用户名”作为主键,我认为这是一个问题的唯一原因,因此对电子邮件地址(如果它是用户名)的任何更新都会导致需要每个链接表被更新。对此进行重新架构以使用独立的 PK 将是解决此问题的首选解决方案,而不是将用户名设为静态。(注意到我对你的原因有一个很大的假设。)