PHP中的暴力/ DoS预防

nic*_*ckf 18 php security ddos brute-force

我正在尝试编写一个脚本,以防止在我正在构建的网站中进行暴力登录尝试.逻辑是这样的:

  1. 用户发送登录信息.
  2. 检查用户名和密码是否正确
    • 如果是,请让他们进来.
    • 如果为否,则在数据库中记录失败的尝试.检查在给定时间范围内是否有太多失败(例如:5分钟内5次):
      • 如果是,则暂停执行10秒:sleep(10)然后向用户报告登录失败.
      • 立即向用户报告登录失败

在向同事解释这个问题时,我被问到如果黑客在一秒内发送了1000个请求,这将有多大帮助.前5个会立即返回,然后剩下的995只需要10秒吗?

我有一种潜在的怀疑,我不完全理解HTTP是如何工作的 - 甚至可能是上述情况,还是服务器将从一个客户端处理的并发请求数量有限制?

更好的解决方案是增加睡眠时间吗?

sleep($numRequestsInLast5Minutes - 5)
Run Code Online (Sandbox Code Playgroud)

所以前5个会很快,然后每个后续的都会增加睡眠.

Kar*_*och 15

问题是用户可访问性和攻击者模型之间的平衡.

第一解决方案

If not password correct for a certain number of time:
    block the user
    send a reset link to the user
Run Code Online (Sandbox Code Playgroud)

用户:可能被阻止,他们不喜欢重置
攻击者:通过尝试向所有用户进行身份验证来阻止所有用户(特别是如果所有登录都是公开的)

二解决方案

If not password correct:
    sleep(amount_of_time)
Run Code Online (Sandbox Code Playgroud)

问题是:'amount_of_time'的价值是多少?

用户:为每个错误等待'amount_of_time'会很烦人
攻击者:继续尝试,测试/秒越低

第三解决方案

If not password correct:
    sleep(amount_of_time)
    amount_of_time = amount_of_time * 2
Run Code Online (Sandbox Code Playgroud)

用户:少烦恼几个密码错误
攻击者:通过发送大量错误密码阻止用户连接

第四解决方案

If not password correct for a certain number of time:
    submit a catchpa
Run Code Online (Sandbox Code Playgroud)

用户:需要解决CAPTCHA(不太复杂)
攻击者:需要解析CAPTCHA(必须复杂)

很好的解决方案(并被许多网站使用)但要小心我们的CAPTCHA.实施.无论如何有一个技巧(见下一个解决方案).

第五解决方案

If not password correct for a certain number of time:
    block the ip
    (eventually) send a reset link
Run Code Online (Sandbox Code Playgroud)

用户:用户可能被阻止,因为他无法正确记住他的密码.
攻击者:使用不同的用户尝试相同的密码,因为阻止是基于用户登录的次数.

最终方案?

If several login attempts failed whatever is the user by an IP :
    print a CAPTCHA for this IP
Run Code Online (Sandbox Code Playgroud)

用户:用户不能被IP阻止,但必须记住其密码.
攻击者:难以进行有效的暴力攻击.

重要的笔记

登录表单或登录提交链接是否被阻止?阻止登录表单是没用的.

对蛮力的抵抗首先是密码复杂性的问题,因此您需要严格的密码策略(特别是在分布式暴力破解的情况下).

我没有提到用盐哈希你的密码的事实,你已经这样做了吗?因为如果访问密码数据库比暴力破解更容易,攻击者将选择这种解决方案("链条只有最薄弱的链条那么强大").


bri*_*gge 13

我建议如果用户尝试失败,比如说超过5次和5分钟,则503 Service Unavailable立即开始返回该IP地址.当登录失败时,您可以使用memcache获取IP的当前错误尝试,然后增加金额,并将其保存到memcache,并在5分钟到期.

您不希望sleep在PHP代码中加入,因为这将允许单个用户创建大量与Web服务器的连接,并可能导致其他用户失望.

由于用户尚未登录,因此您没有会话cookie,并且如果用户试图强行进入帐户,他们可能根本不会提供cookie.

  • @nickf:嗯,你真的不需要阅读研究论文来了解在这种情况下使用sleep()的困境.使用sleep()基本上会暂停脚本的执行,这意味着连接仍然处于打开状态,直到它继续运行.您的服务器可以允许的并发连接数有限制,所以使用sleep()技术上可以让黑客更轻松地对您的服务器执行操作... (2认同)

And*_*ith 2

我不确定最佳实践是什么,但在处理 DoS 攻击时,更好的策略是将流量从服务器上转移出去。设置超时实际上并没有帮助,因为您仍在处理请求并运行 PHP。

您是否考虑过设置另一个 Web 服务器来运行登录页面的更简单的精简版本?当用户尝试次数过多(例如数千次)时,请发送一条消息来配置您的路由器并将该用户重定向到第二个 Web 服务器。

就像当网站受到斜线效应的打击时,许多网站只是将流量重定向,直到流量减少。