Skip to main content

Insecurely generated cookies - SameSite

Need

Secure generation of cookies with proper SameSite attribute

Context

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

Description

Non compliant code

import play.api.mvc._

def login = Action { implicit request =>
val sessionId = java.util.UUID.randomUUID().toString
Ok("Logged in").withCookies(Cookie("sessionId", sessionId))
}

In the above code, a new session cookie is created for each login request but the SameSite attribute is not set. The withCookies method is used to add the cookie to the HTTP response.

The SameSite attribute is a security measure that browsers use to restrict how cookies are sent with cross-site requests. If this attribute is not set, the cookie is sent with all requests, including those that originate from a different site. This can lead to Cross-Site Request Forgery (CSRF) attacks, where an attacker tricks a victim into performing an action that the victim did not intend to do.

In this code, an attacker could potentially trick a user into sending a request to the login route of this application from a different site, causing the application to generate a new session cookie and sending it back to the attacker's site. The attacker could then use this session cookie to impersonate the user in subsequent requests to the application.

To fix this vulnerability, the SameSite attribute should be set to 'Strict' or 'Lax' when creating the cookie. This will instruct the browser to only send the cookie with same-site requests, preventing CSRF attacks.

Steps

  • Update the Play framework version to a version that supports SameSite attribute for cookies.
  • Set the SameSite attribute for the generated cookies to 'Strict' or 'Lax' to prevent cross-site request forgery attacks.
  • Ensure that the SameSite attribute is set for all cookies generated in the application, not just the login cookie.

Compliant code

import play.api.mvc._

def login = Action { implicit request =>
val sessionId = java.util.UUID.randomUUID().toString
val cookie = Cookie("sessionId", sessionId, httpOnly = true, secure = true, sameSite = Some(Cookie.SameSite.Strict))
Ok("Logged in").withCookies(cookie)
}

The updated code now includes the SameSite attribute in the cookie creation process. The SameSite attribute is set to Strict, which means the cookie will only be sent in a first-party context, i.e., only to the site that it originated from. This prevents the cookie from being sent along with requests initiated by third party websites, effectively mitigating the risk of cross-site request forgery (CSRF) attacks.

In addition to setting the SameSite attribute, the httpOnly attribute is set to true to prevent the cookie from being accessed through client-side scripts, and the secure attribute is set to true to ensure the cookie is only sent over secure (HTTPS) connections.

It's important to note that these settings should be applied to all cookies generated by the application, not just the login cookie, to ensure a consistent level of security across all application features.

References