Account lockout
Need
Prevention of unauthorized account lockouts and ensuring continuous user access
Context
• Usage of Ruby 2.6.0 as the programming language for development
• Usage of Ruby on Rails for web application development
Description
1. 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
render "new"...The above code is a simple Ruby on Rails controller for managing user sessions. In the `create` action, it finds the user by the email provided in the form parameters and checks if the user exists and the password is correct. If the authentication is successful, it sets the user_id in the session and redirects the user to the root URL with a success message. If the authentication fails, it sets a flash message and re-renders the login form. However, this code is vulnerable to account lockout attacks. An attacker could repeatedly submit the login form with a valid email but incorrect password, causing the account to be locked out and preventing the legitimate user from logging in. This is because there is no mechanism in place to limit the number of failed login attempts. This vulnerability can cause a denial of service (DoS) if an attacker decides to lock out multiple or all accounts in the system.
2. Steps
• Implement account lockout mechanism
• Limit the number of login attempts
• Track the number of failed login attempts
• Lock the account after a certain number of failed attempts
• Notify the user about the account lockout
• Provide a way for the user to unlock their account
• Consider implementing additional security measures like CAPTCHA
3. Secure code example
class SessionsController < ApplicationController
MAX_LOGIN_ATTEMPTS = 5
def create
user = User.find_by(email: params[:email])
if user && user.authenticate(params[:password])
session[:user_id] = user.id...The updated code introduces a mechanism to limit the number of login attempts and lock the user account after a certain number of failed attempts. The `MAX_LOGIN_ATTEMPTS` constant is used to define the maximum number of failed login attempts allowed before the account is locked. In the `create` method, if the user authentication fails, the `failed_attempts` counter for the user is incremented. The `check_failed_attempts` method is then called to check if the user has exceeded the maximum number of allowed failed login attempts. If the maximum limit is reached, an alert message is displayed to the user indicating that their account has been locked and they need to contact support to unlock it. If the user authentication is successful, the `reset_failed_attempts` method is called to reset the `failed_attempts` counter for the user back to 0. This approach helps to mitigate the risk of account lockout vulnerability by limiting the number of failed login attempts and locking the account when the limit is exceeded.
References
• 087. Account lockout