DEV Community

Block malicious login attempts, but preventing account lock-outs.

Tari R. Alfaro on May 07, 2019

How would you prevent malicious login attempts? I'm curious how the DEV developers(those interested in security) here would prevent mali...
Collapse
 
tarialfaro profile image
Tari R. Alfaro • Edited

Actually, it's not as simple as you think. I'll try to explain it again. Let me demonstrate a attack.

First, I use the IP 192.168.0.16 for example. I am attacking the account with a username of johndoe. I attempt to gain access to johndoe 3 times with this IP. Then, this IP is no longer allowed to attempt to login to any account without first a email being sent to the account's email, for 24 hours. This means I can't attempt to login to johndoe or janedoe for 24 hours with this IP.

So ... I use another IP. 192.168.0.32. I try against johndoe again. 3 times, I failed. Now this IP can't attempt to login anywhere.

Now I change my IP 192.168.0.64. I go again, but I fail yet again another 3 times. I've failed in a total of 9 times. I can no longer use 192.168.0.16, 192.168.0.32 or 192.168.0.64 to attempt to login to ANY accounts.

Now johndoe is locked. I try once again to attack the account, with the IP of 192.168.0.128, but now I am prompted to supply johndoe's email. In some cases, no one may know this account's email.

Crap. Now I can't try to login at all with those three IPs anymore, and now for 24 hours this account is locked down, meaning no one can try to login without having access to the account's email.

By definition, a IP has 3 attempts to gain access to account. After that, if that IP is in use, they must have access to any account's email and receive a special link that allows them to bypass.

Collapse
 
tarialfaro profile image
Tari R. Alfaro • Edited

So this is a combination of account and IP based locking. Essentially each IP has 3 attempts in 24 hours. Each account has 9 attempts in 24 hours.

If either of those reach their limits, they become locked.

But remember, it's implemented in a way to completely stop this form of attack, while only causing minor inconveniences for real users.

Thread Thread
 
artis3n profile image
Ari Kalfus • Edited

I guess the question is why do we want to do this. As Jorge mentioned, blocking by IP is problematic and can inadvertently block legitimate users. Like, I can run my malicious requests through something like mitmproxy and programmatically generate a random IP for every single login request. You can do it through Postman. Trivial to bypass, but possibility of hurting real users.

Per-account, instead of IP, lockouts make more sense to me. Keep a counter in the users table of the DB, increment upon failed login attempts. At whatever threshold you want (I suggest 5 max), lock the user account for 12-24 hours. You can decide if that's enough or if you want to track # of lockouts and eventually require reaching out to support to re-enable an account.

If you really want to track IP and block in that way, I would include an IP blacklist table in the DB and track failed login attempts in the Redis/whatever cache. Once over the limit, write IP to DB. DB function should run every so often and clean IPs from the table after a certain time threshold so they're not permanently blocked. As I finish writing that I think there are cleaner ways to track IP in the DB but that was off the top of my head.

Thread Thread
 
tarialfaro profile image
Tari R. Alfaro • Edited

I do like your idea of caching the IPs, watching them and then persisting their storage if they continue to be suspicious.

However, remember the mechanism.

The definition of locking out an account or IP, means they must supply a email address to that account instead of a username and password.

If the IP 192.168.0.16 attempt 3 times and fails, then a session associated with that IP must supply a email address for all accounts, AKA locking that IP.

Why do this by IP?

Because what if this IP wants to try common passwords against a bunch of accounts? It has three attempts, then the IP is locked.

By doing this, a real user would input their email address, go to their email, and receive the temporary login link. Which means that it's a special, randomly generated link that's not easily guessable. They go there, and then they provide their credentials.

This causes a minor inconvenience for real users, and prevents malicious third-parties from hammering account credentials.

But what about multiple IPs?

We also lock by account.

So by locking by account and IP we benefit from both. And it's done in a way that real users can still login even if their accounts or IPs are locked.

Thread Thread
 
artis3n profile image
Ari Kalfus • Edited

The only effective way to do this type of attack, guessing common passwords against multiple accounts, is in some automated fashion. In which case, anti-CSRF tokens on login via a pre-session prevent that behavior.

Thread Thread
 
tarialfaro profile image
Tari R. Alfaro

Nice, so would having CSRF tokens prevent automated registration and bot spam too?

Thread Thread
 
tarialfaro profile image
Tari R. Alfaro

Also, I don't think CSRF tokens should be the only solution to this issue. What if we're building a RESTful HTTPS API and not a website? Then aren't the CSRF tokens useless?

Thread Thread
 
artis3n profile image
Ari Kalfus • Edited

CSRF will prevent malicious actions like trying to log into someone else's account. A bot could still script it's way into creating an account on your website by taking valid, automated actions. You could do something like Google captcha, but that's such an annoying user experience. Requiring users to confirm account creation via email link is a decent way to stop most bots.

Thread Thread
 
artis3n profile image
Ari Kalfus

Yes, CSRF is not valid if there is no browser involved, as it abuses default browser behavior. Some out-of-band authentication method, like verifying your account creation via email, can help prevent spamming. It doesn't block those attempts, however. Just presents them from working.

Thread Thread
 
artis3n profile image
Ari Kalfus

Also, 2FA is the best way to stop bots IMO. Works as an additional layer of defense against someone malicious trying to log into a user's account as well.

Thread Thread
 
tarialfaro profile image
Tari R. Alfaro

If CSRF token could prevent automated logins, wouldn't it also protect against automated registering?