Lack of protection against brute force attacks - Ruby

Lack of protection against brute force attacks - Ruby

Need

Implementation of strong and effective protection against brute force attacks

Context

  • Usage of Ruby for building web applications and scripting
  • Usage of Ruby on Rails for building web applications

Description

Non compliant code

        class SessionsController < ApplicationController
  def create
    user = User.find_by_email(params[:email])
    if user && user.authenticate(params[:password])
      session[:user_id] = user.id
      redirect_to root_url, notice: "Logged in!"
    else
      flash.now.alert = "Email or password is invalid"
      render "new"
    end
  end
end
        
        

The above code is a simple implementation of an authentication system in a Ruby on Rails application. The create method in the SessionsController is responsible for logging in a user.

When a POST request is made to the /sessions endpoint (which calls the create method), the application tries to find a user with the provided email. If a user with that email exists, it then checks if the provided password matches the password of the found user. If the password is correct, the user is logged in and redirected to the homepage. If the email or password is incorrect, an error message is displayed.

However, this code is vulnerable to brute force attacks. There are no protections in place to limit the number of login attempts. This means that an attacker could use an automated script to repeatedly try different combinations of emails and passwords until they find a combination that works. This is a serious security risk as it could potentially allow an attacker to gain unauthorized access to user accounts.

Steps

  • Implement account lockout mechanism after a certain number of failed login attempts.
  • Use strong and unique passwords for user accounts.
  • Implement CAPTCHA or reCAPTCHA to prevent automated login attempts.
  • Implement rate limiting to restrict the number of login attempts within a specific time period.
  • Implement two-factor authentication to add an extra layer of security.
  • Regularly monitor and analyze login logs for any suspicious activity.
  • Educate users about the importance of using strong passwords and avoiding password reuse.
  • Implement session expiration and automatic logout after a certain period of inactivity.
  • Regularly update and patch the application and its dependencies to fix any security vulnerabilities.

Compliant code

        class SessionsController < ApplicationController
  MAX_LOGIN_ATTEMPTS = 5

  def create
    user = User.find_by_email(params[:email])

    if user && user.failed_attempts < MAX_LOGIN_ATTEMPTS
      if user.authenticate(params[:password])
        user.update(failed_attempts: 0)
        session[:user_id] = user.id
        redirect_to root_url, notice: "Logged in!"
      else
        user.increment!(:failed_attempts)
        flash.now.alert = "Email or password is invalid"
        render "new"
      end
    else
      flash.now.alert = "Your account has been locked due to too many failed login attempts"
      render "new"
    end
  end
end
        
        

The updated code now includes a mechanism to lockout a user account after a certain number of failed login attempts. This is done by adding a failed_attempts field to the User model, which keeps track of the number of consecutive failed login attempts.

When a user tries to log in, the system first checks if the user exists and if the number of failed attempts is less than the maximum allowed. If the user exists and the number of failed attempts is less than the maximum, the system then checks if the provided password is correct. If the password is correct, the failed_attempts field is reset to 0 and the user is logged in. If the password is incorrect, the failed_attempts field is incremented by 1 and the user is not logged in.

If the number of failed attempts is equal to or greater than the maximum allowed, the user is not allowed to log in and a message is displayed indicating that the account has been locked due to too many failed login attempts.

This mechanism helps to protect the system against brute force attacks by limiting the number of login attempts a user can make within a certain period of time.

References