Lack of protection against brute force attacks - Java

Lack of protection against brute force attacks - Java

Need

Implementation of strong and effective brute force protection mechanisms

Context

  • Usage of Java for building cross-platform applications
  • Usage of javax.servlet for building Java web applications
  • Usage of javax.servlet.http for handling HTTP requests and responses in Java Servlets

Description

Non compliant code

        import javax.servlet.*;
import javax.servlet.http.*;

public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        if (username.equals("admin") && password.equals("password123")) {
            // login successful
            request.getSession().setAttribute("user", username);
            response.sendRedirect("dashboard.jsp");
        } else {
            // login failed
            response.sendRedirect("login.jsp");
        }
    }
}
        
        

The above code is a simple login servlet in a Java backend application. It takes the username and password from the HTTP request parameters and checks if they match the hardcoded credentials (admin and password123). If the credentials match, the user is redirected to the dashboard. If they do not match, the user is redirected back to the login page.

This code is vulnerable to brute force attacks. A brute force attack is an attack where an attacker tries many different combinations of usernames and passwords until they find one that works. In this case, an attacker could easily automate this process and try thousands of different combinations of usernames and passwords until they find the correct one.

The problem with the code is that it does not have any protection mechanisms against this type of attack. There are no limits on the number of login attempts a user can make, and there are no delays between login attempts. This means an attacker can make as many login attempts as they want as quickly as they want, increasing the likelihood that they will eventually guess the correct credentials.

Additionally, the credentials are hardcoded into the application, which means every instance of the application has the same credentials. This is a security risk because if an attacker can guess the credentials for one instance of the application, they can access all instances of the application.

Finally, the password is stored in plaintext, which means if an attacker can gain access to the application code, they can easily read the password.

Steps

  • Implement account lockout mechanism
  • Implement CAPTCHA or reCAPTCHA to prevent automated login attempts
  • Enforce strong password policies
  • Implement rate limiting to restrict the number of login attempts within a certain time period
  • Implement multi-factor authentication
  • Use secure session management techniques
  • Implement logging and monitoring to detect and respond to brute force attacks

Compliant code

        import javax.servlet.*;
import javax.servlet.http.*;
import com.google.recaptcha.*;

public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private static final int MAX_ATTEMPTS = 5;
    private static final long LOCKOUT_TIME = 300000; // 5 minutes in milliseconds
    private Map attempts = new HashMap<>();

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String gRecaptchaResponse = request.getParameter("g-recaptcha-response");

        boolean validCaptcha = VerifyRecaptcha.verify(gRecaptchaResponse);

        if (!validCaptcha) {
            response.sendRedirect("login.jsp");
            return;
        }

        Attempt attempt = attempts.get(username);
        if (attempt != null && attempt.isLocked()) {
            response.sendRedirect("login.jsp");
            return;
        }

        if (username.equals("admin") && password.equals("password123")) {
            // login successful
            request.getSession().setAttribute("user", username);
            response.sendRedirect("dashboard.jsp");
        } else {
            // login failed
            if (attempt == null) {
                attempt = new Attempt();
                attempts.put(username, attempt);
            }
            attempt.increment();
            response.sendRedirect("login.jsp");
        }
    }

    private class Attempt {
        private int count;
        private long lastAttemptTime;

        public Attempt() {
            this.count = 0;
            this.lastAttemptTime = System.currentTimeMillis();
        }

        public void increment() {
            if (System.currentTimeMillis() - lastAttemptTime > LOCKOUT_TIME) {
                count = 0;
            }
            count++;
            lastAttemptTime = System.currentTimeMillis();
        }

        public boolean isLocked() {
            return count >= MAX_ATTEMPTS;
        }
    }
}
        
        

The updated code includes several measures to protect against brute force attacks:

1. CAPTCHA Verification: The Google reCAPTCHA service is used to verify that the login attempt is made by a human and not by an automated script. The g-recaptcha-response parameter is sent to the Google reCAPTCHA API for verification. If the verification fails, the user is redirected back to the login page.

2. Account Lockout Mechanism: A simple account lockout mechanism is implemented to lock an account after a certain number of failed login attempts. The MAX_ATTEMPTS constant defines the maximum number of failed attempts allowed. If a user exceeds this limit, their account is locked for a certain period of time, defined by the LOCKOUT_TIME constant.

3. Rate Limiting: The account lockout mechanism also acts as a rate limiter, restricting the number of login attempts a user can make within a certain time period.

4. Session Management: The user's session is managed securely. If the login attempt is successful, the user's username is stored in the session and the user is redirected to the dashboard page. If the login attempt fails, the user is redirected back to the login page.

5. Logging and Monitoring: Although not explicitly shown in the code, it is recommended to implement logging and monitoring to detect and respond to brute force attacks. This could include logging failed login attempts and setting up alerts for multiple failed attempts from the same IP address.

Please note that this code does not include the implementation of multi-factor authentication and strong password policies, which are also recommended for protecting against brute force attacks.

References