Yesterday, I tried to log in to my bank’s website for the first time in a few months. I couldn’t remember my password, because I change them frequently, so I tried a password, then another, and then another, which is, I hope, what most reasonable people do when they forget their password.
To my great dismay, after the third attempt, I got a message saying “Your account has been locked. Please call the bank to unlock it”. Given that this is my company bank, which is in the UK, and I am in Greece, this is extremely inconvenient. I now hate my bank (more than before).
Here are a few tips, if you are developing any sort of application that has authentication/logins, although I feel I will be preaching to the choir:
Rate limiting
You pretty much have to rate-limit logins (in case you aren’t familiar, rate-limiting is the practice of stopping people from being able to log in after a few wrong tries). Otherwise, you are just inviting brute-forcers, botnets, and other unhygienic people to try to steal your users’ passwords. There are some considerations when implementing rate-limiting, though.
The purpose of rate-limiting is to stop people trying to brute-force passwords, but still allow legitimate users to log in properly. A word to the wise: DO NOT LIMIT LOGINS TO THREE. There is no earthly reason why you need to set your limit that low. Many, many legitimate users will regularly have three failed attempts, even if just because they left their Caps Lock key on by mistake.
Three attempts will, indeed, prevent crackers from brute-forcing anyone, but will also greatly annoy legitimate users. 100 attempts per day will make it equally hard for crackers to brute-force an account (assuming it doesn’t use one of the 100 most used passwords), while not being an inconvenience to any legitimate user.
Actual limits
If a user runs out of wrong attempts, there are two things you can do. By the way, you should never limit correct logins, except if the user is actually limited. If the user has run into the limit, they should not be allowed to continue, even if they supply the correct password, that’s the whole point of limiting (otherwise a cracker could just continue trying and would find the password eventually).
Banning logins
The first thing you can do is completely disallow them from trying to log in again. You could display a message saying “you are trying to log in too much, please try later”, remove the login form from the page, or present the limit to the user any other way you want that will let them know they can try later.
CAPTCHAs
Another direction you can go is presenting the user with a CAPTCHA. This is a bit harder for automated bots to crack, in that they will also have to solve the CAPTCHA somehow. Many bots just give up, as their operators don’t go through the hassle of solving the CAPTCHAs, or they move on to another site. This works best if your accounts are low-profile or low-value, as it is an effective deterrent then.
By only showing the CAPTCHA after a few failed attempts, you don’t inconvenience legitimate users who know their password, but you do get the added security. Keep in mind that, since CAPTCHAs don’t inconvenience people as much as banning them outright does, so you can set the limit much lower (I believe 3-5 attempts per day is a sane limit, and you can reset it after a successful login).
Epilogue
I hope this short overview has helped crystallize how to properly safeguard your users’ accounts without being annoying. To remind you, if you aren’t using a KDF (PBKDF2, bcrypt, scrypt) for storing the passwords, stop what you’re doing and go change that first. Otherwise, you can start implementing these limits if you don’t have them already.
I might have missed something, so please leave comments if you have any feedback.