Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Block request for multiple unsuccessful logins for a period of time

I have a web site and I want to block request from BOTs and attempt brute force login to my web site.

Now I'm using Session for storing login attempt and show captcha after 3 unsuccessful login but there is a problem.Session will be removed, if user closes the browser.

What kind of solution I should consider to prevent BOTs and brute force login? What property of user system or browser I should store to manage his/her next login?

Edit 1)

I don't use ASP.NET Membership provider. I'm using my own authentication and authorization classes

like image 851
Arian Avatar asked May 21 '15 09:05

Arian


People also ask

How long do you have to wait after too many failed login attempts?

Solution 1: Wait for 24 Hours If you sign in with Google prompts, make sure you don't lose access to the device. This can create serious problems if you lose your phone, or it suddenly gets damaged.

How many unsuccessful attempts does an user account get locked?

A locked account can't be used until you reset it or until the number of minutes specified by the Account lockout duration policy setting expires. You can set a value from 1 through 999 failed sign-in attempts, or you can specify that the account will never be locked by setting the value to 0.

How do I fix too many login attempts Osrs?

Repeated attempts to log in can make the situation worse, so we highly recommend waiting at least 30 minutes between attempts if you receive this error. Logging in via the Jagex Launcher should resolve this error. Simply use your existing login credentials to play. Check the Jagex Launcher FAQ for more information.

What is unsuccessful login attempts?

A failed login attempt is defined as 6 consecutive unsuccessful login attempts made from a device, with each subsequent unsuccessful attempt counting as an additional failed attempt.


4 Answers

You can't use session, as it requires the client to store a cookie for you, and an attacker is not going to help you out. You will need some global state.

You needn't bother tracking IP addresses, as a bad guy will just use an Anonymyzing Proxy.

Don't use account lock-out unless you have to (PCI requirement), as this just lets the attacker DoS your users.

You also want to avoid DoS-ing yourself by making your server do too much work.

This works:

Upon unsuccessful authentication, store username in global state, along with count. Synchronized count++ if more unsuccessful authentications with that username. I use redis for this.

If count >= threshold, then demand solved CAPTCHA value before proceeding. Show CAPTCHA on login screen.

Upon successful authentication, clear stored username in global state. Give user "trusted user agent" HMAC'd cookie, so they don't have to CAPTCHA in the future for that username on that UA.

You can do the same for passwords, but probably with a higher threshold.

If you don't like CAPTCHA then demand Proof of Work, for example by making the client calculate and submit the prime factors of a very large number.

While you're at it, make sure you are using bcrypt to hash your passwords, and that the cost factor is high enough that it takes >= 250ms to hash a password. This slows down your server but also slows down an attacker. Avoid hashing unless they pass the CAPTCHA (if required).

Encourage users to use long, complicated, memorable? passwords, so that they're harder to brute-force.

like image 142
Neil McGuigan Avatar answered Sep 25 '22 18:09

Neil McGuigan


The easiest would be to front your solution with a CDN provider such as cloudflare (https://www.cloudflare.com/features-security) that will detect bots for you. Lots of the CDNs offer this, and cloudflare have a free tariff.

Alternatively if you are attempting to do this yourself, then you can count the number of attempts per username in your database and present a captcha based on this count.

like image 22
ABrowne Avatar answered Sep 28 '22 18:09

ABrowne


Identify invalid login based on IpAddress(anonymous proxy).That Each invalid login ip and login count&time that will stored in Application State.

Create Class InvalidLogin

public class InvalidLogin
{
    public string IP { get; set; }
    public DateTime Attempttime { get; set; }
    public int AttemptCount { get; set; }
}

Login Event

protected void Login_Click(object sender, EventArgs e)
        {
            bool Testsuccessfullogin = false;
            if (Testsuccessfullogin)
            {
                //Your code after successfull login
            }
            else
            {
               //Invalid Login --- Capture Each login event based on IP
                string strIp;
                strIp = Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; //when user is behind proxy server
                if (strIp == null)
                {
                    strIp = Request.ServerVariables["REMOTE_ADDR"];//Without proxy
                }

                List<InvalidLogin> user = null;
                if (HttpContext.Current.Application["Users"] == null) //Adding List to Application State
                {
                    user = new List<InvalidLogin>();
                }
                else
                {
                    user = (List<InvalidLogin>)HttpContext.Current.Application["Users"];
                }
                var remove = user.RemoveAll(x => x.Attempttime < DateTime.Now.AddMinutes(-15));//Remove IP Before 15 minutes(Give 15 Min Time Next Login)
                var checkLogged = user.Find(x => x.IP == strIp);
                if (checkLogged == null)
                {
                    user.Add(new InvalidLogin
                    {
                        IP = strIp,
                        Attempttime = DateTime.Now,
                        AttemptCount = 1

                    });
                     Application.Lock();
                     HttpContext.Current.Application["Users"] = user;
                      Application.UnLock();
                }
                else
                {
                    if (checkLogged.AttemptCount < 4)
                    {
                        checkLogged.Attempttime = DateTime.Now;
                        checkLogged.AttemptCount++;
                        Application.Lock();
                        HttpContext.Current.Application["Users"] = user;
                        Application.UnLock();
                    }
                }



                if (checkLogged != null)
                {
                    if (checkLogged.AttemptCount > 3)
                    {
                        captcha.Visible = true;  //Showing captcha 
                    }
                }




            }
        }
like image 44
Benjamin Avatar answered Sep 29 '22 18:09

Benjamin


If you are using your own authentication and authorization classes, you need to count the number of failed attempt to login for each user and it's date and time.

If the number of attempts is reached the limit that you will break the next login process with error message like "Your account was blocked for a 15 minutes, please try again later."

For example. Table of logins is named [Logins].

You need to add new colums:
1. [LastLoginAttemptAt] DATETIME NULL
2. [LoginFailedAttemptsCount] INT NOT NULL DEFAULT 0

So, your class Login will have these new fields:

public class Login {
    public DateTime? LastLoginAttemptAt {get;set;}
    public int LoginFailedAttemptsCount {get;set;}
}

Also you need to store somewere configuration variable - the value of max number of failed attempts to login and block period.

const int MaxNumberOfFailedAttemptsToLogin = 10;
const int BlockMinutesAfterLimitFailedAttemptsToLogin = 15; // 15 min

On a signIn method you will do the following (primitive example of code, not a prod-version):

public void SignIn(string username, string password)
{    
    var login = _userService.TryGetLogin(username);
    if (login == null){
        // Login by username not found.
        // Return error message "Invalid username or password"
        return;
    }

    if (login.LoginFailedAttemptsCount > MaxNumberOfFailedAttemptsToLogin
    && login.LastLoginAttemptAt.HasValue
    && DateTime.Now < login.LastLoginAttemptAt.Value.AddMinutes(BlockMinutesAfterLimitFailedAttemptsToLogin))
    {
        // Login is blocked, need to break the process.
        // Return error message "Your account was blocked 
        // for a 15 minutes, please try again later."
        return;
    } else {
        login.LoginFailedAttemptsCount = 0;
        login.LastLoginAttemptAt = DateTime.Now;
    }

    var success = login.ValidatePassword(password);
    if (!success)
    {
        // Invalid password, need to update the number of attempts.
        login.LastLoginAttemptAt = DateTime.Now; //or UTC
        login.LoginFailedAttemptsCount++;
        // Update(login);
        // Return error message "Invalid username or password"
        return;
    } else {
        login.LoginFailedAttemptsCount = 0;
        login.LastLoginAttemptAt = DateTime.Now;
        // Update(login);
        // Success!
    }
}
like image 38
Yuriy A. Avatar answered Sep 26 '22 18:09

Yuriy A.