Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security: how to implement Brute Force Detection (BFD)?

My web applications security is handled by Spring Security 3.02 but I can't find any out of the box support for Brute Force Detection.

I would like to implement some application level BFD protection. For example by storing failed login attempt per user in the database (JPA). The attacked user accounts could then get a lockout period or a forced account re-activation by e-mail.

What's the best way to implement this with Spring Security? Does any body have example code or best practices on this?

like image 391
Kdeveloper Avatar asked Apr 21 '10 08:04

Kdeveloper


2 Answers

It's not that hard to roll your own BFD. As in Spring Security 3.0 you can simply add Application listeners (thanks Stephen C for pointing me in the correct direction).

This listener will be called when authentication failures appear:

@Component
public class AuthenticationFailureListener
    implements ApplicationListener<AuthenticationFailureBadCredentialsEvent> {

  @Autowired
  private UserDao userDao;

  public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent ev) {

    String username = ev.getAuthentication().getName();

    User user = userDao.find("name", username);
    if (user != null) { // only for existing users
            user.reportLoginFailure();
            userDao.commit();
    }
  }
}

Each authentication failure will now inform the user. The user for example increments an authentication failure counter and deactivates it self when a certain threshold is reached.

When a user is correctly authenticated the below listener will inform the user (who for example can reset it’s authentication failure counters):

@Component
public class AuthenticationSuccessEventListener
    implements ApplicationListener<AuthenticationSuccessEvent>{

  @Autowired
  private UserDao userDao;

  public void onApplicationEvent(AuthenticationSuccessEvent event) {

    String username = event.getAuthentication().getName();

    User user = userDao.find("name", username);
    user.reportLoginOK();
    userDao.commit();
  }
}

The above listeners will not need additional XML configuration and are picked up automatically by Spring (if they are in Spring component-scan package).

Depending on you transaction configuration this solution could miss some failed login counts if they happen near simultaneously. This can be prevented if you update the counter with a single UPDATE query instead of loading the user and then save the changes.

Above listeners can also be extended to detect other BDF patterns, for example a single IP that is doing a scan on lot’s of (random) user names.

like image 83
Kdeveloper Avatar answered Nov 04 '22 05:11

Kdeveloper


You should also know that locking an attacked account means making your service DOSable.

The well known example is: you provide an auction service, Bob wants to buy some position and attacks Alice's account, so instead of making bets Alice tries to restore her account while Bob gets the position. Even temporary (5 seconds) locks may prevent Alice from using the service as she needs.

like image 26
Andrey Minogin Avatar answered Nov 04 '22 04:11

Andrey Minogin