Insecure functionality - Session management - Ruby

Insecure functionality - Session management - Ruby

Need

Secure session management

Context

  • Requirement of Ruby 2.0 or higher for running the application
  • 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
      session[:expires_at] = Time.current + 2.hours
    else
      render 'new'
    end
  end

  def update
    if session[:expires_at] < Time.current
      session[:expires_at] = params[:new_expiration_time]
    end
  end
end
        
        

The above code represents a typical session management in a Ruby on Rails application. The session is created in the create method, where a user is authenticated based on their email and password. If the authentication is successful, a session is initiated with a user_id and an expires_at time, which is set to 2 hours from the current time.

The vulnerability lies in the update method. This method allows for the modification of the expires_at time of a session, even if it's already expired. The if condition checks if the current time is later than the expires_at time, and if so, it allows for the expires_at time to be updated with a new value, new_expiration_time, which is passed in the parameters.

This means that if a malicious user obtains an expired session token, they can modify the expires_at time and make the token functional again, which could potentially allow them to perform unauthorized actions in the application. This is a significant security risk and a violation of secure session management principles.

Steps

  • Use a secure session management mechanism provided by the Ruby on Rails framework.
  • Avoid manually setting the expiration time of the session token.
  • Instead, rely on the default session expiration mechanism provided by the framework.
  • Ensure that the session token is invalidated and cannot be reused after it expires.
  • Implement proper authentication and authorization mechanisms to prevent unauthorized access to sensitive functionality.
  • Regularly review and update the application's session management implementation to address any new vulnerabilities or best practices.

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
    else
      render 'new'
    end
  end

  def update
    if session[:expires_at] < Time.current
      redirect_to new_session_path, alert: 'Session has expired. Please log in again.'
    end
  end
end
        
        

The updated code now uses the secure session management mechanism provided by the Ruby on Rails framework. The create method in the SessionsController class authenticates the user and sets the user_id in the session. The update method checks if the session has expired and if so, it redirects the user to the login page with an alert message, instead of allowing the session expiration time to be manually updated.

This way, we are relying on the default session expiration mechanism provided by the framework, which is more secure and less prone to manipulation. The session token is invalidated and cannot be reused after it expires, preventing unauthorized access to sensitive functionality.

It's important to regularly review and update the application's session management implementation to address any new vulnerabilities or best practices. This includes implementing proper authentication and authorization mechanisms, and avoiding the manual setting of session token expiration times.

References