Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way for a Spring MVC web app to detect a brute force attack?

Are there any features specifically in Spring 3.0 MVC that would help implementing detection of a brute force attack on the authentication/login page of a web app?

like image 954
Michael Volk Avatar asked Apr 16 '11 12:04

Michael Volk


3 Answers

Long-proven practice is to introduce a random but sizable delay if authentication has failed.

This way legitimate users will log on right away, but an attacker will spend 500ms-1s per try, which makes the whole brute-force idea impractical (will take forever).

Occasional failed login by legitimate users will cause them only a minor delay and will go unnoticed.

If you need to be notified on repeated failed logins, you need to implement a report printing number of consequential failed logins per user, order by that number desc limit 100.

P.S. Here is a post explaining how to get notified on login attempt. Following the same approach one can introduce a delay, I believe.

like image 167
Vladimir Dyuzhev Avatar answered Oct 12 '22 20:10

Vladimir Dyuzhev


It is possible by some configurations and coding in Spring security.

By the way, I do not suggest to make some delay in front of suspicious invalid login trials. You may make some delay to respond to a suspicious login attempt but this delay costs you to suspend a thread for a while in your application. This may provide DoS or DDoS attack on your system if there are high amount of invalid logins happen simultaneously to your application.

The better approach is to make a fast response to a suspicious invalid login but at the same time to suspend the user account by which the user is trying to login. In this way, brute force attack avoidance does not lead to provision of Dos or DDoS attack.

Nevertheless, suspension of user account would also provide a way for DoS attack, for it may lead to failure in delivery of service to real user. But, correct security scenarios would be helpful in these cases. For example, if a brute force attack is detected, you may:

  • show some Captcha,
  • suspend the account, email or SMS the account owner for password change
  • or, suspend the account for a period of time while notifying the account owner for password change,
  • ...

All of this depends to your domain and service scenarios. As an example, you may implement your own UserDetailsService and detect brute force attack in this implementation.

To implement the last scenario by Spring Security, the following code declares an authentication-manager which is passed a custom UserDetailsService which type is JdbcDaoImpl here (Note that package names and queries must be modified to your own package and data model).

<authentication-manager alias="authenticationManager" xmlns="http://www.springframework.org/schema/security">
    <authentication-provider user-service-ref="CustomUserDetailsService" />           
</authentication-manager>

<!--
This bean is to provide jdbc-user-service.
Also, it provides a way to avoid BFD along with AuthenticationFailureListener
-->
<bean id="CustomUserDetailsService" class="com.example.CustomUserDetailsService">
    <property name="dataSource" ref="dataSource" />
    <property name="usersByUsernameQuery" value="SELECT user_client.user_name, user_client.password, user.is_active
                                   FROM user_client INNER JOIN user ON user_client.fk_user = user.ID
                                   WHERE user_client.user_name=? "/>
    <property name="authoritiesByUsernameQuery" value="SELECT user_client.user_name, CONCAT('ROLE_',user_client.client_id)
                                   FROM user_client WHERE user_client.user_name=? "/>
</bean>

The CustomUserDetailsService detects if there is a brute force attack happening or not, along with AuthenticationFailureListener that I discuss soon. FailedLoginCacheManager is a ehcache wrapper that maintains the failed logins (usernames) with their relative failed amounts. The cache is set with a proper timeToIdleSeconds to make the account suspension temporary.

public class CustomUserDetailsService extends JdbcDaoImpl {

@Autowired
private FailedLoginCacheManager cacheManager;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    if (cacheManager.isBruteForceAttackLogin(username)) {
     //throw some security exception
     ...
    }
    return super.loadUserByUsername(username);
}

}

Also, a ApplicationListener is implemented to detect failed login attempts and preserve them inside the ehcache.

@Component public class AuthenticationFailureListener implements ApplicationListener<AuthenticationFailureBadCredentialsEvent> {

@Autowired
private FailedLoginCacheManager cacheManager;

@Override
public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent event) {
    UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) event.getSource();
    String userName = token.getPrincipal().toString();
    cacheManager.updateLoginFailureStatus(userName);
}}

There is no need to discuss more about FailedLoginCacheManager service but two main methods that are discussed here could be implemented like the following methods:

public void updateLoginFailureStatus(String userName) {
    Cache cache = manager.getCache(CACHE_NAME);

    Element element = cache.get(userName);
    if (isValid(element)) {
        int failureCount = (Integer)element.getObjectValue();
        cache.remove(userName);
        cache.put(new Element(userName, ++failureCount));
    } else {
        cache.put(new Element(userName, 1));
    }

}

public boolean isBruteForceAttackLogin(String username) {
    Cache cache = manager.getCache(CACHE_NAME);
    Element element = cache.get(username);
    if (isValid(element)) {
        int failureCount = (Integer)element.getObjectValue();
        return failureCount >= 3;
    } else {
        return false;
    }
}
like image 42
Youness Avatar answered Oct 12 '22 20:10

Youness


Surprisingly, I couldn't find anything in the reference docs for either Spring MVC or Spring Security.

I did, however, find this 3 year old tutorial that describes how it can be done using Splunk.

like image 23
Sean Patrick Floyd Avatar answered Oct 12 '22 18:10

Sean Patrick Floyd