views:

1267

answers:

7

I want to implement an efficient mechanism to throttle login attemps in my Java web application, to prevent brute-force attacks on user accounts.

Jeff explained the why, but not the how.

Simon Willison showed an implementation in Python for Django: That doesn't really help me along as I can't use memcached nor Django.

Porting his ideas from scratch doesn't seem like a great either - I don't want to reinvent the wheel.

I found one Java implementation, though it seems rather naiive: Instead of a LRU cache, it just clears all entries after 15 minutes.

EHCache could be an alternative for memcached, but I don't have any experience with it and don't really want to intoduce yet another technology if there are better alternatives for this task.

So, whats a good way to implement login throttling in Java?

A: 

I've just completed the web security course run by aspect security and one of the suggestions that came out of that was to just include a natural delay in any login attempt - the theory being that a 1 or 2 second delay is nothing to a real-user but will seriously hamper brute force attacks.

MrWiggles
Any login might kill the user experience though.
Loki
Any failed login is standard in unix world, but the web app part implies that an attacker could do it in multiple threads so a simple timeout wont do, you have to store the login attempt somewhere and make some code to access and verify it.
Loki
Just delaying all attemps doesn't stop someone from running 50 requests in parallel. Thats why Simon Willison stores the IP adress together with the timestamp in the cache.
Jörn Zaefferer
I was assuming that a standard "3 strikes and you're locked out" rule would be in effect too. It doesn't stop you ddos'ing the site but it does stop you brute forcing accounts
MrWiggles
+1  A: 

I think even EHCache is killing a fly with a napalm bomb. The problem is simple and so is the implementation.

I suggest using a servlet filter a the top level so that as little processing as possible is done.

Create a class to store the following:

  • The number of attempts (count)
  • The time

Now, the code is simple in a sunchronized block:

if userid not in attemptMap:
    attemptMap.add ( userid, new attemptItem ( userid, 1, now ) )
else
    tmp = attemptMap.get ( userid )
    if (acquire lock for tmp) :
      if tmp.time + 30 > now :
          tmp.count = 0
          tmp.time = now
      tmp.count++
      if tmp.count > 3 :
          error=true
      release lock for tmp
    else : error=true

thats it man (as long as the code is synchronized).

Loki
I've asked for a solution in Java, this obviously isn't Java. Apart from that, considering your own comments: I'm looking for a solid and well tested solution, not something thrown together in five minutes. A throttling system that deadlocks after a few hours or something isn't very useful.
Jörn Zaefferer
What I'm telling you is that no library implements that directly. All you need is a synchronized way to put data (user, count and time or just user and time) and verify it. Many libraries offer the synchronized storage, it's up to you to adapt it. I'm offering the scaffolding of a solution.
Loki
A simple synchronized map or vector ought to do it. You don't need systems like ehCache just for that.
Loki
@Jorn, he gave you pseudo-code, that's not good enough for you?
matt b
+1  A: 

I've used a Login Attempt count field with user details. When it gets to 50, correct passwords are rejected and the user has to perform a password reset.

Dead account
Sounds like an easy way to DoS certain users.
Jörn Zaefferer
As would having ANY form of exponential delay. More importantly, as time goes on it becomes easier and easier to DOS the user (as each additional intentional fail works for twice as long as the last)
SCdF
A: 

What about an exponential increase in time between login attemps?

simonlord
+1  A: 

I think Jeff explained the how quite well...

1st failed login no delay

2nd failed login 2 sec delay

3rd failed login 4 sec delay

4th failed login 8 sec delay

5th failed login 16 sec delay

And so on. Alternately, you could display a CAPTCHA after the fourth attempt.

dotjoe
A: 

One that hasn't been mentioned is make them answer forgotten password question(s) after so many bad attempts + enter their password

Element
A: 

EHCache is pretty good, and more importantly Not Written By You, so you don't have to reimplement features and possibly get them wrong.

My solution would involve either EHCache or something simpler (if it was a small app and I didn't really care about concurrency performance) in the login code.

You would store, per IP, a fail count and a timestamp.

  • Each time you make a login attempt, workout whether they are allowed to using the fail count and the timestamp.
  • Each time you make an allowed login attempt and fail, increment the failed count by 1 and record the fail time.
  • Each time you make an allowed login attempt and succeed clear the info for that IP.
SCdF