PHP 中的蛮力/DoS 预防 [英] Brute-force/DoS prevention in PHP
问题描述
我正在尝试编写一个脚本来防止我正在构建的网站中的暴力登录尝试.逻辑是这样的:
I am trying to write a script to prevent brute-force login attempts in a website I'm building. The logic goes something like this:
- 用户发送登录信息.
- 检查用户名和密码是否正确
- 如果是,让他们进来.
- 如果否,则在数据库中记录一次失败的尝试.检查在给定时间范围内是否有太多失败(例如:5 分钟内有 5 次):
- 如果是,则暂停执行 10 秒:
sleep(10)
,然后向用户报告登录失败. - 立即向用户报告登录失败
- 如果是,则暂停执行 10 秒:
- User sends login information.
- Check if username and password is correct
- If Yes, let them in.
- If No, record a failed attempt in the database. Check if there's too many fails within a given timeframe (eg: 5 in 5 minutes):
- If Yes, then pause execution for 10 seconds:
sleep(10)
, then report a login failure to the user. - Report a login failure to the user immediately
- If Yes, then pause execution for 10 seconds:
我向一位同事解释了这一点,有人问我,如果黑客在一秒钟内发送 1000 个请求,这会有什么帮助.前5个会立即返回,然后剩下的995个都只需要10秒吗?
Explaining this to a co-worker, I was asked how this would help if a hacker sent, say, 1000 requests in one second. Would the first 5 would return immediately, and then the remaining 995 all take only 10 seconds?
我偷偷怀疑我并不完全了解 HTTP 的工作原理 - 上述情况是否可能,或者服务器将处理来自一个客户端的并发请求数量是否有限制?
I have a sneaking suspicion that I don't fully understand how HTTP works - is that situation above even possible, or is there a limit to the number of concurrent requests that a server will handle from one client?
增加睡眠时间是更好的解决方案吗?
Would a better solution be to have an increasing sleep time?
sleep($numRequestsInLast5Minutes - 5)
所以前 5 个会很快,然后每个后续都会增加睡眠.
So the first 5 would be fast, and then every subsequent one would increase the sleep.
推荐答案
问题在于用户可访问性和攻击者模型之间的平衡.
The problem is the balance between user accessibility and attacker model.
If not password correct for a certain number of time:
block the user
send a reset link to the user
用户:可能被屏蔽,他们不喜欢重置
攻击者:通过尝试向所有用户进行身份验证来阻止所有用户(尤其是在所有登录信息都是公开可用的情况下)
User: could be blocked, and they don't like to reset
Attacker: blocked all users by trying to authenticate to all users (especially if all logins are publicly available)
If not password correct:
sleep(amount_of_time)
问题是:'amount_of_time' 的值是多少?
The question is: what is the value of 'amount_of_time' ?
用户:为每个错误等待amount_of_time"可能很烦人
攻击者:不断尝试,以较低的测试/秒
User: can be annoying to wait 'amount_of_time' for each error
Attacker: keep trying, with lower test / seconds
If not password correct:
sleep(amount_of_time)
amount_of_time = amount_of_time * 2
用户:少一些密码错误就不那么烦人了
攻击者:通过发送大量错误密码阻止用户连接
User: less annoying for few password mistakes
Attacker: block the user to connect by sending lot of incorrect password
If not password correct for a certain number of time:
submit a CAPTCHA
用户:需要解析验证码(不要太复杂)
攻击者:需要解析验证码(必须复杂)
User: need to resolve the CAPTCHA (not too complex)
Attacker: need to resolve the CAPTCHA (must be complex)
很好的解决方案(并被很多网站使用)但是请注意我们的验证码.实施.无论如何,有一个技巧(见下一个解决方案).
Good solution (and used by a lot of sites) but be careful to our CAPTCHA. implementation. Anyway there is a trick (see next solution).
If not password correct for a certain number of time:
block the IP
(eventually) send a reset link
用户:用户可能因为无法正确记住密码而被阻止.
攻击者:用不同的用户尝试相同的密码,因为阻止是基于用户登录的次数.
User: User may be blocked because he cannot correctly remember his password.
Attacker: trying the same password with different user, because blocking is based on number of login by user.
If several login attempts failed whatever is the user by an IP :
print a CAPTCHA for this IP
用户:用户不能被 IP 屏蔽,但必须记住其密码.
攻击者:很难进行有效的蛮力攻击.
User: User cannot be IP blocked but must remember its password.
Attacker: difficult to have an efficient brute-force attack.
登录表单或登录提交链接是否被阻止?阻止登录表单是没有用的.
Is the login form or the login submit link which is blocked ? Blocking the login form is useless.
抵抗暴力首先是密码复杂性的问题,因此您需要严格的密码策略(尤其是在分布式暴力的情况下).
Resistance to brute-force is FIRST a problem of password complexity, so you need a strict password policy (especially in the case of distributed brute force).
我没有提到用盐对密码进行散列的事实,您已经在这样做了吗?因为如果访问密码数据库比暴力破解更容易,攻击者就会选择这种解决方案(一条链的强度取决于其最薄弱的环节").
I don't mention the fact to hash your passwords with salt, you're already doing this right ? Because if it is easier to access to the password database than brute-forcing, the attacker will choose this solution ("A chain is only as strong as its weakest link").
这篇关于PHP 中的蛮力/DoS 预防的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!