Skip to main content

Insecure session management

Need

Secure session management

Context

  • Usage of Scala for building scalable and high-performance applications
  • Usage of play.api.mvc for handling HTTP requests and responses in Play Framework

Description

Non compliant code

import play.api.mvc._

class SessionController extends Controller {

def login = Action { implicit request =>
val username = request.body.asFormUrlEncoded.get("username")(0)
val password = request.body.asFormUrlEncoded.get("password")(0)

// Assume we have a method `validateLogin` to validate user credentials
if (validateLogin(username, password)) {
Ok("Welcome!").withSession("username" -> username)
} else {
Unauthorized("Wrong credentials.")
}
}

def logout = Action { implicit request =>
Ok("Bye!").withNewSession
}
}

In the above code, we have a SessionController class which handles user login and logout. When a user logs in, the login method is called. This method validates the user's credentials and if they are valid, it creates a new session with the user's username.

The logout method, when called, does not invalidate the current session. Instead, it just creates a new session. This means the old session with the user's username is still valid and can be used to make requests to the server. This is the insecure session management vulnerability.

In a secure session management system, the session token should be invalidated when the user logs out. This ensures that even if an attacker gets hold of a session token, they cannot use it to impersonate the user after the user has logged out.

Steps

  • Implement session timeout to invalidate sessions after a certain period of inactivity.
  • Use secure session management techniques such as using secure cookies or encrypting session data.
  • Ensure that session tokens are securely generated and cannot be easily guessed or brute-forced.
  • Implement proper logout functionality to invalidate the session token when the user logs out.
  • Regularly review and update session management code to address any new vulnerabilities or best practices.

Compliant code

import play.api.mvc._
import play.api.libs.typedmap.TypedKey

class SessionController extends Controller {

// Define a key for the last activity timestamp
val LastActivityKey = TypedKey[Long]("lastActivity")

def login = Action { implicit request =>
val username = request.body.asFormUrlEncoded.get("username")(0)
val password = request.body.asFormUrlEncoded.get("password")(0)

// Assume we have a method `validateLogin` to validate user credentials
if (validateLogin(username, password)) {
// Set the last activity timestamp to the current time
Ok("Welcome!").withSession("username" -> username).withAttrs(Attrs(LastActivityKey -> System.currentTimeMillis))
} else {
Unauthorized("Wrong credentials.")
}
}

def logout = Action { implicit request =>
// Invalidate the session on logout
Ok("Bye!").withNewSession
}

// Add a new action to check the session timeout
def checkTimeout = Action { implicit request =>
request.attrs.get(LastActivityKey) match {
case Some(lastActivity) =>
if (System.currentTimeMillis - lastActivity > 30 * 60 * 1000) { // 30 minutes timeout
// If the session has timed out, invalidate it
Ok("Session timed out.").withNewSession
} else {
// If the session has not timed out, update the last activity timestamp
Ok("Session active.").withAttrs(Attrs(LastActivityKey -> System.currentTimeMillis))
}
case None =>
Unauthorized("No session.")
}
}
}

The updated code includes a mechanism to handle session timeouts. This is done by storing a timestamp of the last activity in the session attributes. Each time a request is made, the checkTimeout action is called to check if the session has timed out. If the session has been inactive for more than 30 minutes, it is invalidated. Otherwise, the last activity timestamp is updated.

The logout action now invalidates the session, ensuring that the session token cannot be used after the user has logged out.

These changes help to secure the session management by preventing session tokens from being used indefinitely after they have been issued. This reduces the risk of session tokens being used maliciously if they are intercepted or otherwise obtained by an attacker.

References