Insecure session expiration time - Scala

Insecure session expiration time - Scala

Need

Enforce secure session expiration time

Context

  • Usage of Scala 2.13 for developing scalable and high-performance applications
  • Usage of play.api.mvc for handling HTTP requests and building web applications in Play Framework
  • Usage of play.api.mvc.ControllerComponents for handling HTTP requests in Play Framework
  • Usage of play.api.mvc.BaseController for creating base controllers in Play Framework
  • Usage of play.api.mvc.Request for handling HTTP requests in Play Framework
  • Usage of play.api.mvc.AnyContent for handling any type of content in Play Framework
  • Usage of play.api.mvc.Action for handling HTTP requests in Play Framework
  • Usage of play.api.mvc.Request for handling HTTP requests in Play Framework
  • Usage of play.api.mvc.AnyContent for handling any type of content in Play Framework
  • Usage of play.api.mvc.Result for handling HTTP responses in Play Framework
  • Usage of play.api.mvc.Results for handling HTTP responses in Play Framework
  • Usage of play.api.mvc.Session for managing session data in Play Framework

Description

Non compliant code

        import play.api.mvc._

class HomeController @Inject()(val controllerComponents: ControllerComponents) extends BaseController {

  def index() = Action { implicit request: Request[AnyContent] =>
    Ok("Welcome!").withSession("user" -> "username")
  }
}
        
        

The Play Framework provides an easy way to deal with HTTP sessions. In the above code, a new session is started whenever the 'index' endpoint is hit. The session is associated with the key 'user' and the value 'username'.

However, the problem with this code is that the session does not expire after a certain period of inactivity. In this case, the session remains active indefinitely until the server is restarted or the user logs out. This is a security vulnerability because if an attacker gets hold of a user's session, they can use it to impersonate the user for an unlimited amount of time.

The vulnerability lies in the absence of a session expiration time, which should be set to ensure that sessions automatically expire after a certain period of inactivity. In this case, the requirement is for sessions to expire after 5 minutes of inactivity.

Steps

  • Set a proper session expiration time for user sessions.
  • Implement a mechanism to track user activity and update the session expiration time accordingly.
  • Use a secure session storage mechanism to store session data.
  • Regularly review and update the session expiration time based on security requirements.
  • Test the session expiration functionality to ensure it is working as expected.

Compliant code

        import play.api.mvc._
import play.api.libs.typedmap.TypedKey
import java.time.{Instant, Duration}

class HomeController @Inject()(val controllerComponents: ControllerComponents) extends BaseController {

  // Define a key to store the last activity time in the session
  val LastActivityTime: TypedKey[Instant] = TypedKey[Instant]("lastActivityTime")

  def index() = Action { implicit request: Request[AnyContent] =>
    val now = Instant.now()
    val lastActivityTime = request.attrs.get(LastActivityTime).getOrElse(now)
    val duration = Duration.between(lastActivityTime, now)

    if (duration.toMinutes > 5) {
      Unauthorized("Session expired")
    } else {
      Ok("Welcome!").withSession("user" -> "username").addingToSession(LastActivityTime -> now.toString)
    }
  }
}
        
        

The updated code introduces a mechanism to track the last activity time of a user session. This is done by storing the last activity time in the session using the TypedKey LastActivityTime.

In the index action, we first get the current time ( now) and then retrieve the last activity time from the session. If there is no last activity time stored in the session (which would be the case for a new session), we use the current time as the last activity time.

Next, we calculate the duration between the last activity time and the current time. If this duration is more than 5 minutes, we return an Unauthorized response, effectively ending the session. If the duration is 5 minutes or less, we update the session with the current time as the new last activity time and return a Ok response.

This way, we ensure that user sessions expire after 5 minutes of inactivity, addressing the identified vulnerability.

References