PHP 中的暴力破解/DoS 防御

发布于 2024-08-11 00:59:10 字数 1431 浏览 2 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

掩于岁月 2024-08-18 00:59:10

问题在于用户可访问性和攻击者模型之间的平衡。

第一个解决方案

If not password correct for a certain number of time:
    block the user
    send a reset link to the user

用户:可能被阻止,并且他们不喜欢重置
攻击者:通过尝试对所有用户进行身份验证来阻止所有用户(特别是在所有登录信息都是公开可用的情况下)

第二个解决方案

If not password correct:
    sleep(amount_of_time)

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

用户:等待每个错误“amount_of_time”可能会很烦人
攻击者:继续尝试,测试/秒数较低

第三种解决方案

If not password correct:
    sleep(amount_of_time)
    amount_of_time = amount_of_time * 2

用户:少数密码错误不那么烦人
攻击者:通过发送大量错误密码来阻止用户连接

第四种解决方案

If not password correct for a certain number of time:
    submit a CAPTCHA

用户:需要解析验证码(不要太复杂)
攻击者:需要解析验证码(必须很复杂)

很好的解决方案(并且被很多网站使用),但是小心我们的验证码。实施。无论如何,有一个技巧(请参阅下一个解决方案)。

第五种解决方案

If not password correct for a certain number of time:
    block the IP
    (eventually) send a reset link

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

最终解决方案?

If several login attempts failed whatever is the user by an IP :
    print a CAPTCHA for this IP

用户:用户不能被IP封锁,但必须记住其密码。
攻击者:很难进行有效的暴力攻击。

重要提示

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

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

我没有提到用盐对密码进行哈希处理的事实,您已经这样做了,对吗?因为如果访问密码数据库比暴力破解更容易,攻击者就会选择这种解决方案(“一条链的强度取决于其最薄弱的一环”)。

The problem is the balance between user accessibility and attacker model.

First Solution

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)

Second solution

If not password correct:
    sleep(amount_of_time)

The question is: what is the value of 'amount_of_time' ?

User: can be annoying to wait 'amount_of_time' for each error
Attacker: keep trying, with lower test / seconds

Third Solution

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

Fourth Solution

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).

Fifth 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.

Final Solution ?

If several login attempts failed whatever is the user by an IP :
    print a CAPTCHA for this IP

User: User cannot be IP blocked but must remember its password.
Attacker: difficult to have an efficient brute-force attack.

The important notes

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").

月隐月明月朦胧 2024-08-18 00:59:10

我建议,如果用户尝试不成功,例如超过五次五分钟,则立即开始针对该 IP 地址返回 503 Service Unavailable。当登录失败时,您可以使用 memcache 获取当前 IP 的错误尝试,然后增加该数量,并将其保存回 memcache,并在 5 分钟内过期。

您不想在 PHP 代码中设置sleep,因为这将允许单个用户创建与您的 Web 服务器的大量连接,并可能导致其他用户瘫痪。

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

I would suggest if the user has tried unsuccessfully, say more than five times and five minutes, you start returning a 503 Service Unavailable immediately, for that IP address. When a login fails, you could use memcache to get the current bad attempts for an IP, and then increment the amount, and save it back to memcache with a 5 minute expiry.

You don't want to put a sleep in your PHP code, as that will allow a single user to create lots of connections to your web server, and potentially bring down other users.

Since the user hasn't logged in, you don't have a session cookie, and if the user is trying to brute force their way into an account, they may not present a cookie at all.

寻梦旅人 2024-08-18 00:59:10

我已经使用过类似的东西...

  1. 检查用户名和密码

    1.1 如果不匹配,则记录该组合上次登录失败的时间以及登录失败的次数。

    1.2 每次失败都会导致能够登录之间的等待时间,例如failsCount * 30秒,最多可达最大值(例如10分钟)。

  • 这意味着暴力攻击将花费越来越长的时间。
  • 它可以锁定用户 - 但在锁定期间尝试登录时不会计算失败的登录。这应该可以最大限度地减少它。

我已经开发了这个,但尚未将其发布到野外,因此任何反馈将不胜感激。

I have used something like this...

  1. Check username and password

    1.1 If no match then, record last failed login time for that combo and number of failed logins.

    1.2 Each fail makes the wait between being able to login something like failsCount * 30 seconds, up to a maximum (such as 10 minutes).

  • This means a brute force attack will exponentially take longer and longer.
  • It could lock a user out - but it will not count a failed login whilst trying to login during the lockout period. This should minimise it.

I've developed this but not released it into the wild yet, so any feedback would be appreciated.

自此以后,行同陌路 2024-08-18 00:59:10

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

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

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

I am not sure what the best practice is, but when dealing with DoS attacks, a better strategy is to actually divert traffic away from your server. Setting timeouts won't actually help because you're still processing the request and running PHP.

Have you considered setting up another web server running a simpler stripped down version of your login page? When the user tries too many times (e.g., thousands of times), send a message to configure your router and redirect this user to the second web server.

It's like when websites get hit with the slashdot effect, many of them just redirect traffic away until traffic is reduced.

我一直都在从未离去 2024-08-18 00:59:10

我在 PHP 中创建了一个负责暴力攻击防护的类。

https://github.com/ejfrancis/BruteForceBlocker

它将整个站点范围内的所有失败登录记录在数据库中表中,如果过去 10 分钟(或您选择的任何时间范围)内登录失败的次数超过设定限制,则在再次登录之前会强制执行时间延迟和/或验证码要求。

例子:

//build throttle settings array. (# recent failed logins => response).

$throttle_settings = [
    50 => 2,            //delay in seconds
    150 => 4,           //delay in seconds
    300 => 'captcha'    //captcha 
];
 
$BFBresponse = BruteForceBlocker::getLoginStatus($throttle_settings); 

//$throttle_settings is an optional parameter. if it's not included,the default settings array in BruteForceBlocker.php will be used

switch ($BFBresponse['status']){

    case 'safe':
        //safe to login
        break;
    case 'error':
        //error occured. get message
        $error_message = $BFBresponse['message'];
        break;
    case 'delay':
        //time delay required before next login
        $remaining_delay_in_seconds = $BFBresponse['message'];
        break;
    case 'captcha':
        //captcha required
        break;
}

I made a class that takes care of brute force attack protection in PHP.

https://github.com/ejfrancis/BruteForceBlocker

it logs all failed logins site-wide in a db table, and if the number of failed logins in the last 10 minutes (or whatever time frame you choose) is over a set limit, it enforces a time delay and/or a captcha requirement before logging in again.

example:

//build throttle settings array. (# recent failed logins => response).

$throttle_settings = [
    50 => 2,            //delay in seconds
    150 => 4,           //delay in seconds
    300 => 'captcha'    //captcha 
];
 
$BFBresponse = BruteForceBlocker::getLoginStatus($throttle_settings); 

//$throttle_settings is an optional parameter. if it's not included,the default settings array in BruteForceBlocker.php will be used

switch ($BFBresponse['status']){

    case 'safe':
        //safe to login
        break;
    case 'error':
        //error occured. get message
        $error_message = $BFBresponse['message'];
        break;
    case 'delay':
        //time delay required before next login
        $remaining_delay_in_seconds = $BFBresponse['message'];
        break;
    case 'captcha':
        //captcha required
        break;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文