防止字典攻击对Web应用程序的影响

19

如何防止字典攻击?我想到了几种方案,但它们似乎都存在一些问题:

  1. 在X次失败的登录尝试后锁定用户。问题:容易被转化为拒绝服务攻击,在短时间内锁定很多用户。
  2. 针对用户名,每次登录失败时逐步增加响应时间。问题:字典攻击可能使用相同的密码但不同的用户名。
  3. 针对IP地址,每次登录失败时逐步增加响应时间。问题:易于通过欺骗IP地址来规避。
  4. 在会话中,每次登录失败时逐步增加响应时间。问题:易于通过创建新会话的字典攻击来规避。

不要重复造轮子,看看其他网站是如何做的。为什么不使用验证码? - Konerak
8个回答

22
我很喜欢Gmail的反暴力破解系统。它基于用户可以累积的“热度”,一旦用户过热,就会提示其进行验证码验证。您可以使用SQL数据库或redis incr来跟踪热度。热度分配给IP地址。由于三次握手,在互联网上不可能“欺骗”TCP连接,但代理服务器很多,IP地址非常便宜。代理服务器通常用于发送垃圾邮件,您可以检查黑名单并自动提示他们进行验证码验证。
对系统的每个不良行为都会更新热度表。例如,登录失败将累积35%的热度。一旦热度水平大于或等于100%,则强制用户解决验证码。解决验证码将“冷却”该IP地址。热度表可以包含一个时间戳列,在更新时设置为当前时间。24小时后,热度可以返回到0。 reCaptcha是您可以使用的最安全的验证码。

3
我一直都支持您的第三个选项 - 基于客户端IP地址进行锁定或限速。其他选项都不值得麻烦,正如您所说的那样。
伪造IP地址是可能的,但这并不能打败这种反制措施。如果您指的是技术意义上的“伪造” - 伪造TCP数据包头 - 那么这对攻击者没有太大好处,因为即使他们猜对了正确的密码,他们也不会收到告诉他们的响应。当然,他们仍然可以使用代理,但代理的数量是有限的。即使攻击者有1000个可用的代理,并且您允许每个IP尝试10次,也只有10000次尝试。如果您强制要求任何密码复杂性(例如需要字母数字密码),那么这将不足以猜测很多。
这就足以阻止大多数脚本小子。如果您面对一个更有决心的攻击者,您可能需要实施某种全站监控,以便检测到正在进行许多尝试(因此可能存在攻击),并以某种方式“锁定”,例如使用CAPTCHA。我不喜欢一直使用CAPTCHA - 它们只会带来更多的麻烦。
最终,用户自己选择安全密码(尽管您可以帮助他们)。如果他们选择“Password1”作为密码,那么无论您做什么都无法阻止黑客入侵他们的账户。

1

也许你需要在你的网页表单上实现验证码


1

安全性、可用性和易用性之间存在永恒的权衡,这意味着不存在完美的解决方案。

根据您的情况,一个不错的折衷方案是使用选项 #1 并添加验证码。在三次失败尝试后锁定账户,但如果正确解决了验证码,则允许后续的登录尝试。


1

我也建议使用第三个选项。虽然它对于拥有大量代理(或机器人网络)的攻击者不太好,但我仍然认为它是大多数网站的最佳答案。(Gmail面临与大多数网站不同的威胁,因此需要不同的响应。)

一个真实的例子:
我参与的一个大型在线游戏会跟踪过去5分钟内每个IP地址的失败登录尝试次数。一旦任何一个IP地址累积了5次错误的登录尝试(无论成功尝试的次数如何),该地址将被阻止45分钟。

为什么这有效
我坐下来计算了一下,高度智能的黑客可能会在大约100次尝试中破解一个帐户(可能更糟)。因此,最坏的情况下,攻击者每100分钟(每个IP地址)就会破解1个帐户。对于这个特定网站的威胁来说,这已经足够保护了。我们的帐户真的不值那么多钱。您需要确定(对于您的网站)需要多少保护。如果需要,您可以将时间窗口延长到30分钟,使其需要3倍的时间。

重要提示
不要在成功登录后重置计数(无论是用于解决方案3还是上述热图),否则攻击者将只尝试黑客入侵3个帐户,然后成功登录到他们已经控制的某个帐户(自己或已经被攻击的帐户),并且永远不会被限制。


这样的系统难道不意味着一个知道游戏其他用户IP地址的人可以通过IP地址欺骗来关闭该IP地址吗? - Christian
1
@Christian:不行,因为TCP使用三次握手来建立连接,而使用伪造的地址无法完成这个过程,因为攻击者无法接收到服务器的ACK(确认应答)。ACK将被发送到虚假的IP地址而不是攻击者的真实地址。如果没有从伪造的地址建立连接,攻击者将无法尝试从该地址登录。 - Dave Sherohman

1

首先,阻止用户选择常见密码。在您的数据库中添加“黑名单”,并检查新密码是否与其匹配。您可以使用许多密码或单词列表之一来填充它,例如这里:

http://securityoverride.org/infusions/pro_download_panel/download.php?did=66

其次,考虑临时锁定。如果您有一个“用户”表,请添加“LastLoginAttemptedOn”和“FailedLoginAttempts”列。每次用户尝试登录时更新这些值。当用户成功登录时,将FailedLoginAttempts重置为0。当FailedLoginAttempts达到4(或您喜欢的任何数字)时,不要让用户在LastLoginAttemptedOn之后的5分钟内尝试登录。在计时器重置之前不要更新此列,以防止4分钟后尝试重置计时器。当计时器重置时,将FailedLoginAttempts重置为0,以便他们有更多的重试机会。

0

这取决于你所说的 "prevent" 是什么意思。

如果你不想让他们浪费你的带宽,限速、锁定等都是可行的选择。使用热表会有一些开销——你必须创建和维护逻辑、存储和管理 "热图" 等等。我也看到过一些基于 IP 地理位置的系统,如果用户尝试从 "遥远" 或 "未知" 的 IP 登录,会弹出验证码或更改其登录配置文件。

如果你只想大幅降低字典攻击的效果,可以在密码哈希中加盐。


4
盐值加密和密码哈希如何降低字典攻击的有效性?据我所知,盐值加密和哈希只有在对密码进行加密时才有用,因为这样可以避免在数据库中以明文形式存储密码。但最终,一个选择不当的密码仍然会容易受到字典攻击的威胁,无论它在存储之前是否被盐值加密和哈希处理过。 - Kevin Pang

0
如果您正在为一个安全性非常重要的应用程序编程,那么可以禁止包含字典单词的密码。 您不必将QWERTY作为有效密码。

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