限制(和记录)登录尝试的最佳方法

24

显然,限制登录尝试的机制是一项安全要求。虽然我喜欢尝试之间呈指数增加的概念,但我不确定存储信息的方式。我也对替代解决方案感兴趣,最好不包括验证码。

我猜想由于阻止cookie或自动清除它们,cookie不起作用,但会话会起作用吗?还是必须在数据库中存储?由于不知道正在使用哪些方法,因此我不知道什么是实际可行的。


请参见:https://dev59.com/tHRB5IYBdhLWcg3w4bGv - Kzqai
8个回答

23

在你的用户表中使用'failed_login_attempts'和'failed_login_time'列。第一列表示登录失败次数,每次失败都会加1,而成功登录则会将其重置为0。第二列可以让你比较当前时间和最后一次登录失败的时间。

你的代码可以利用数据库中的这些数据来确定锁定用户的等待时间、允许登录之间的时间等等。


22
另外,我发现你还应该储存无效用户名的登录失败尝试。如果你只是在有效用户名上锁定失败的尝试,那么你就会暴露可用的用户名,这是不可取的。 - Andrew
2
我喜欢基于两个标准存储失败信息:如果使用了有效的用户名,则对用户名和IP计数失败,否则仅对IP计数失败。如果正在攻击特定账户,则它将独立于特定IP锁定该账户,同时任何一个恶意IP都会导致网站范围的锁定。此外,重要的是存储明确的锁定过期时间,并在每次尝试时更新锁定过期时间。 - Jody Bruchon
如果系统在呈现有效的用户名和密码后向用户显示登录延迟(失败后强制等待),是否存在弱点?我认为所有其他人,无论如何,都应该只看到“没有匹配此信息”。 - chrisinmtown
如果需要阻止IP,则需要另一个IP表。 - csr-nontol

7
假设谷歌已经进行了必要的可用性测试(这不是一个不公平的假设)并决定使用验证码,我建议跟随他们的决定。
当我是一个真正的用户并忘记了我的密码时(由于有许多网站和相关密码,这种情况经常发生,特别是对我而言),增加超时时间会令人沮丧。

1
我同意这个观点。对于非必要服务来说,增加超时时间是非常令人沮丧的。 - Anand

5
在我看来,将尝试存储到数据库中是最佳解决方案,因为它可以提供安全漏洞尝试的审计记录。根据您的应用程序,这可能或可能不是法律要求。
通过记录所有错误尝试,您还可以收集更高级别的信息,例如请求是否来自一个IP地址(即某人/事物正在尝试暴力攻击),以便您可以阻止该IP地址。这可能是非常有用的信息。
一旦确定了阈值,为什么不强制他们请求将电子邮件发送到其电子邮件地址(类似于“我忘记了我的密码”),或者您可以采用CAPCHA方法。

5
这篇文章中的答案优先考虑基于数据库的解决方案,因为它们提供了记录结构,使审核和锁定逻辑变得方便。

虽然这里的答案解决了对个人用户的猜测攻击,但这种方法的一个主要问题是它将系统留给了拒绝服务攻击。来自世界各地的任何请求都不应该触发数据库工作。

应该在 req/ res 周期的早期实施替代(或附加)安全层,以保护应用程序和数据库免受执行昂贵且不必要的锁定操作的影响。

Express-Brute 是一个很好的例子,它利用 Redis 缓存来过滤恶意请求,同时允许诚实的请求。


2

当你知道哪个用户ID被攻击时,保持一个标志,当它达到阈值时,停止接受该用户的任何请求。但这意味着你要为每个用户存储额外的数据值。

我喜欢指数级增长尝试之间时间的概念,[...]

除了使用指数级增长的时间,你可以实际上在连续的尝试之间设置随机延迟。

也许如果你解释一下你正在使用的技术,这里的人们将能够提供更具体的示例。


2
锁定策略固然很好,但需要保持平衡。
一个考虑因素是思考用户名的构建方式 - 是否容易猜测?它们是否可以被枚举?
我曾参与一次外部应用程序渗透测试,测试对象是一家拥有员工门户网站、提供Outlook Web Access / Intranet服务和特定应用程序的互联网公司。很容易通过网站本身以及谷歌、Facebook、LinkedIn等平台来枚举用户(包括高管/管理团队)。一旦获取了用户名登录格式(名字和姓氏作为一个字符串输入),我就能够根据他们的三次错误登录策略将数百个用户锁定在外面。

1

将信息存储在服务器端。这样可以防御来自多台机器的分布式攻击。


1

你可能想要在一定时间内阻止登录,例如在3次失败尝试后的10分钟内。我认为指数级增加的时间听起来不错。是的,在服务器端会话或数据库中存储信息。数据库更好。不使用cookie,因为用户很容易操纵。

你可能还想将这些尝试映射到客户端IP地址,因为很可能有效用户会收到被阻止的消息,而其他人正在尝试猜测有效用户的密码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接