logo

Session Fixation - Ruby


Need

Prevention of session fixation attacks


Context

  1. Usage of Ruby 2.5.0 as the programming language for development
  2. Usage of Ruby on Rails for building web applications

Description

Insecure Code Example

class SessionsController < ApplicationController
  def create
    user = User.find_by(email: params[:email])

    if user && user.authenticate(params[:password])
      if cookies[:user_id]
        session[:user_id] = cookies[:user_id]
      else
        session[:user_id] = user.id
      end
      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
    redirect_to root_url, notice: "Logged out!"
  end
end

In the `create` method of `SessionsController`, the application is trying to authenticate a user based on their email and password. If the user is authenticated, the application checks if there is a `user_id` cookie. If this cookie exists, the application sets the `session[:user_id]` to the value of the cookie. If the cookie does not exist, it sets the `session[:user_id]` to the user's ID. The problem with this code is that it allows for session fixation. An attacker can set the `user_id` cookie to a value they know and then trick a user into logging in. Since the application sets the `session[:user_id]` to the value of the `user_id` cookie if it exists, the attacker can hijack the user's session. In the `destroy` method, the application sets `session[:user_id]` to `nil`, effectively logging the user out. However, this does not change the `user_id` cookie, so an attacker can still hijack the session if they know the value of the `user_id` cookie. This vulnerability can be exploited by an attacker to gain unauthorized access to a user's session, potentially leading to unauthorized actions and data exposure.

Steps

  1. Generate a new session ID for the user after a successful login.
  2. Invalidate the existing session ID and create a new session ID for the user upon logout.
  3. Ensure that the session ID is not predictable or easily guessable.
  4. Implement secure session management practices, such as using secure cookies and enabling secure flag for cookies.
  5. Consider implementing additional security measures like session expiration and session timeout.
  6. Regularly review and update the session management code to address any new vulnerabilities or best practices.

Secure Code Example

class SessionsController < ApplicationController
  def create
    user = User.find_by(email: params[:email])

    if user && user.authenticate(params[:password])
      reset_session
      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

  def destroy
    reset_session
    redirect_to root_url, notice: "Logged out!"
  end
end

The updated code now includes a call to `reset_session` in both the `create` and `destroy` methods. This ensures that a new session ID is generated for the user after a successful login and that the existing session ID is invalidated upon logout. In the `create` method, `reset_session` is called before setting `session[:user_id] = user.id`. This ensures that a new session ID is generated for the user after they successfully authenticate. In the `destroy` method, `reset_session` is called to invalidate the existing session ID when the user logs out. This change addresses the session fixation vulnerability by ensuring that the session ID changes after login and logout, making it harder for an attacker to hijack the user's session. In addition to this, it's recommended to implement secure session management practices, such as using secure cookies and enabling the secure flag for cookies. Also, consider implementing additional security measures like session expiration and session timeout. Regularly review and update the session management code to address any new vulnerabilities or best practices.


References

  • 280 - Session Fixation

  • Last updated

    2023/09/18