Concurrent sessions control bypass - C-Sharp

Concurrent sessions control bypass - C-Sharp

Need

Enforcement of concurrent session control

Context

  • Usage of C# for building robust and scalable applications
  • Usage of System for low-level operating system interactions and utilities
  • Usage of Microsoft.AspNetCore.Http for handling HTTP requests and responses in ASP.NET Core applications

Description

Non compliant code

        using System;
using Microsoft.AspNetCore.Http;

public class SessionController : ControllerBase
{
    public IActionResult Index()
    {
        if (HttpContext.Session.GetString("UserSession") == null)
        {
            HttpContext.Session.SetString("UserSession", Guid.NewGuid().ToString());
            return View();
        }
        else
        {
            return RedirectToAction("Error", "Home");
        }
    }
}
        
        

The above code is a simple implementation of session control in an ASP.NET Core application. In the Index action of the SessionController, it checks if there is a session with key "UserSession". If there is no such session, it creates a new one and returns the View(). If there is a session already, it redirects the user to an error page.

The vulnerability lies in the fact that there is no real control over concurrent sessions. If a user already has a session and tries to open a new one, they'll be redirected to an error page. However, if they bypass this by directly going to a valid URL in the application, they can start a new session.

This is because the application only checks for the existence of a session when the Index action is called, but not when other actions are called. Therefore, a user can bypass the session control just by avoiding the Index page. This could potentially allow a user to have multiple active sessions at once, which can lead to various security issues such as session fixation attacks, session sidejacking, and cross-site request forgery.

Steps

  • Implement a mechanism to track active sessions in the application.
  • When a new session is started, check if the maximum number of concurrent sessions has been reached.
  • If the maximum number of concurrent sessions has been reached, prevent the new session from being created and display an error message to the user.
  • If the maximum number of concurrent sessions has not been reached, allow the new session to be created.
  • Ensure that the session tracking mechanism is secure and cannot be easily bypassed.
  • Consider implementing additional security measures such as session expiration and session timeout to further enhance session control.

Compliant code

        using System;
using System.Collections.Concurrent;
using Microsoft.AspNetCore.Http;

public class SessionController : ControllerBase
{
    private static ConcurrentDictionary activeSessions = new ConcurrentDictionary();

    public IActionResult Index()
    {
        if (HttpContext.Session.GetString("UserSession") == null)
        {
            if (activeSessions.Count >= MAX_SESSIONS)
            {
                return RedirectToAction("Error", "Home");
            }
            else
            {
                string sessionId = Guid.NewGuid().ToString();
                HttpContext.Session.SetString("UserSession", sessionId);
                activeSessions.TryAdd(sessionId, DateTime.Now);
                return View();
            }
        }
        else
        {
            string sessionId = HttpContext.Session.GetString("UserSession");
            if (activeSessions.ContainsKey(sessionId))
            {
                return View();
            }
            else
            {
                return RedirectToAction("Error", "Home");
            }
        }
    }
}
        
        

The updated code now includes a mechanism to track active sessions in the application. This is done using a ConcurrentDictionary named activeSessions that stores the session ID and the time it was created.

When a new session is requested, the code first checks if the maximum number of concurrent sessions ( MAX_SESSIONS) has been reached. If it has, the user is redirected to an error page. If it hasn't, a new session is created and added to the activeSessions dictionary.

If a session already exists for the user, the code checks if it is in the activeSessions dictionary. If it is, the user is allowed to continue. If it isn't, the user is redirected to an error page.

This approach ensures that the session tracking mechanism is secure and cannot be easily bypassed. It also provides a foundation for implementing additional security measures such as session expiration and session timeout.

References