Insecurely generated token - Lifespan - Ruby

Insecurely generated token - Lifespan - Ruby

Need

Securely generate session tokens with shorter expiration times

Context

  • Usage of Ruby for building dynamic and object-oriented applications
  • 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] = 5.days.from_now
      redirect_to root_url, notice: "Logged in!"
    else
      flash.now.alert = "Email or password is invalid"
      render "new"
    end
  end
end
        
        

In the above code, a new session is created when a user logs in. The create method in the SessionsController is responsible for this. It first finds the user by their email and then authenticates them using the provided password. If the authentication is successful, the user's ID is stored in the session and an expiration time is set for the session token. The session token is set to expire 5 days from the time of creation.

The vulnerability here is the insecurely generated token lifespan. The session token has a fixed lifespan of 5 days, which is a long time for a session token to be valid. This allows potential attackers to use the session token for malicious activities within this period if they manage to get hold of it.

This is a security risk as the longer a session token is valid, the more time an attacker has to use it for malicious purposes. A more secure approach would be to have a shorter lifespan for the session token and to implement a mechanism to refresh the token.

Steps

  • Generate a cryptographically secure random token for the session token.
  • Set an appropriate expiration time for the session token, considering factors such as session length and sensitivity of the data.
  • Store the session token securely, such as in a secure cookie or in a database with proper encryption.
  • Implement a mechanism to rotate session tokens periodically to mitigate the risk of token leakage.
  • Ensure that the session token is invalidated and removed from storage when the session expires or the user logs out.
  • Regularly review and update the session token generation and management process to stay up-to-date with best practices and security standards.

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] = 30.minutes.from_now
      session[:token] = SecureRandom.hex(64)
      redirect_to root_url, notice: "Logged in!"
    else
      flash.now.alert = "Email or password is invalid"
      render "new"
    end
  end

  def destroy
    session[:user_id] = nil
    session[:expires_at] = nil
    session[:token] = nil
    redirect_to root_url, notice: "Logged out!"
  end
end
        
        

The updated code now generates a cryptographically secure random token using SecureRandom.hex(64) and stores it in the session. This token is unique for each session and is hard to guess due to its randomness and length.

The session expiration time has been reduced to 30 minutes from 5 days. This reduces the window of opportunity for an attacker if they manage to steal a session token.

The destroy method has been added to invalidate the session when the user logs out. This method sets the user_id, expires_at, and token in the session to nil, effectively removing them from the session.

This approach enhances the security of the session management in the application by ensuring that session tokens are securely generated, have a reasonable lifespan, and are properly invalidated when no longer needed.

References