logo

Concurrent Sessions Control Bypass - Elixir


Need

Prevent concurrent sessions from a single user account to maintain traceability


Context

  1. Usage of Elixir 1.12 for building scalable and fault-tolerant applications
  2. Usage of Phoenix Framework 1.6 for web development

Description

Insecure Code Example

defmodule MyAppWeb.SessionController do
  use MyAppWeb, :controller
  def create(conn, %{"user" => user_params}) do
    case MyApp.Auth.authenticate(user_params) do
      {:ok, user} ->
        conn
        |> put_session(:user_id, user.id)
        |> redirect(to: "/dashboard")
      _ ->
        conn
    end
  end
end

The code snippet depicts a controller in a Phoenix application where users can log in without the application terminating their previous sessions. This would allow an attacker who gained access to a user's account to use it concurrently with the legitimate user, causing potential loss of traceability.

Steps

  1. Maintain a server-side record of active user sessions
  2. Immediately invalidate any existing sessions for a user when a new login occurs

Secure Code Example

defmodule MyAppWeb.SessionController do
  use MyAppWeb, :controller
  def create(conn, %{"user" => user_params}) do
    case MyApp.Auth.authenticate(user_params) do
      {:ok, user} ->
        MyApp.Session.invalidate_user_sessions(user)
        conn
        |> put_session(:user_id, user.id)
        |> redirect(to: "/dashboard")
      _ ->
        conn
    end
  end
end

In the fixed code, upon successful authentication, any existing sessions for the user are invalidated before a new one is created. This ensures that only one session can be active at a time for each user, preventing concurrent session control bypass.


References

  • 301 - Concurrent Sessions Control Bypass

  • Last updated

    2023/09/18