Brute force protect your website

Nov 27, 2006

On a website with the ability for users to logon, it is a good idea to have some sort of password policy. The most widely used contains minimum requirements for the length of the password and that the individual characters must be a mixture of numbers, letters and special characters. This is pretty much standard and they make it much more difficult to break into your system.

Eventually, these passwords will be broken and for a brute force robot it’s only a matter of time. That’s why it is a good idea to protect against brute force attacks by limiting the number of retries you can take to login if you forget the right password.

I’ve written a few methods that limits the number of retries to 5. When the fifth bad attempt to logon is reached, you are unable to login to the user account for five minutes. No other users are affected, only the one that is being brute forced.

The Code


private int NumberOfLogonAttemps()

{

  if (Cache[txtUserName.Text] == null)

    return 0;

 

  return (int)Cache[txtUserName.Text];

}

 

private void ClearLogonCounter()

{

  if (Cache[txtUserName.Text] != null)

  {

    Cache.Remove(txtUserName.Text);

  }

}

 

private void CountLogonAttempt()

{

  if (Cache[txtUserName.Text] == null)

  {

    Cache.Insert(txtUserName.Text, 1, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(5));

  }

  else

  {

    int tries = (int)Cache[txtUserName.Text];

    Cache[txtUserName.Text] = tries + 1;

  }
}

Example of use

To use these three methods you have to call them from the logon buttons click event handler.

protected void BtnLoginClick(object sender, EventArgs e)

{

  CountLogonAttempt();

  if (NumberOfLogonAttemps() > 5)

  {

    Status.InnerHtml = "User has been locked for 5 minutes";

  }

  else

  {

    ClearLogonCounter();

    LogOn();

  }
}

This is very simple to implement and should it become an issue to logon for the users, you can raise the threshold to 10 retries.

* Only $4.95/month ASP.NET & Windows 2008 + IIS 7 Hosting! FREE SQL Included

Comments (11) -

 Scott Guthrie
Scott Guthrie
11/27/2006 4:21:13 PM #

One feature I'd recommend looking at is the built-in attack support within the Membership API and provider with ASP.NET 2.0.  This alllows you to configure a window and the maximum number of failed login attempts that are allowed in that window.

Once that threshold is hit, the account is disabled until an admin re-activates it.

Hope this helps,

Scott

Ted Jardine
Ted Jardine
11/27/2006 6:40:27 PM #

Well, I was going to mention the lockout feature of the Membership API, but scottgu of all people beat me to it...

But of course, for pre-2.0 sites and 2.0 sites that don't use the Membership API, that's a handy implementation.

Mads Kristensen
Mads Kristensen
11/27/2006 7:14:19 PM #

I know about the lockout feature of the Membership API, but I have a couple of websites with completely custom memberships. Before they get rewritten to use the Membership API, I'm stock with this custom implementation to prevent brute force attacks.

Jesper
Jesper
11/28/2006 4:39:59 AM #

Another way of implementing this, would be setting a delay that is doubled for every attempt. Setting it to one second for the first failed attempt, then 2, 4...well, you know where I'm going.

For those who simply forgot their passwords, this will be a minor issue. A brute force robot will be delayed enormously.

 Damien Guard
Damien Guard
11/28/2006 10:20:18 AM #

Of course doing this means anyone can set a script going to prevent a legitimate user from accessing the site.

All you would need is their username.

Sounds like a DOS to me albeit per-user rather than per-server.

Perhaps locking it down by IP would help mitigate this somewhat.

[)amien

Mads Kristensen
Mads Kristensen
11/28/2006 1:30:47 PM #

Damien: A "little" DOS attack like this is way better than anyone actually breaking into the system. Besides, as you point out, it is only per user not the entire server.

Eirik
Eirik
11/29/2006 9:56:08 AM #

I'm having a problem with the code. The Cache never expires. Do you have any suggestions on what could be causing this?
The code that insert the cache:
Cache.Insert(txtUsername.Text, 1, null, DateTime.Now.AddMinutes(5), Cache.NoSlidingExpiration);

Mads Kristensen
Mads Kristensen
11/29/2006 10:10:52 AM #

Eirik, that seems odd. From what I can see, it should expire in five minutes if it's not being inserted again in the meantime.

Eirik
Eirik
11/29/2006 11:13:18 AM #

ok. i'll do some more debugging. probably just a stupid bug

 Boris Yeltsin
Boris Yeltsin
12/7/2006 9:22:59 AM #

This doesn't stop another form of attack that successfully infiltrated one site I run.

One of our competitors decided to start storing all the passwords their users logged in with (as their passwords were normally hashed), and then they wrote a script to try the same usernames and passwords en masse against our web site until they found matching accounts which let them in. They only tried each account once (because they had a password to try for each username).

We had to reset all our user's passwords and add a CAPTCHA to the login form Frown

In future I'll replace the visible CAPTCHA with an invisible one to make it easier on the users - I'm essentially just trying to remove robots.

Mads Kristensen
Mads Kristensen
12/7/2006 9:37:31 AM #

That sounds like a horrible attack you've been subject to. If you want to try an invisible captcha, I've written one that might suit your needs at www.madskristensen.dk/.../...oid+Comment+Spam.aspx

Comments are closed

About the author

Mads Kristensen

Mads Kristensen
Program Manager at the Microsoft Web Platform team and founder of BlogEngine.NET.

More...

Month List

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer’s view in any way.