Skip to main content

Sensitive information sent via URL parameters - Session

Need

Secure transmission of sensitive information in session tokens

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._

object SessionController extends Controller {

def login = Action { request =>
val jwtToken = request.getQueryString("jwtToken")
jwtToken match {
case Some(token) => {
// Set the JWT token as a session variable
Ok("Logged in").withSession("jwtToken" -> token)
}
case None => Unauthorized("No JWT token provided")
}
}

def secureAction = Action { request =>
request.session.get("jwtToken").map { token =>
// Perform secure action
Ok("Secure action performed")
}.getOrElse {
Unauthorized("No JWT token in session")
}
}
}

The above Scala code snippet represents a controller in a Play Framework application that handles user login and a secure action. The login action reads a JWT token from the URL parameters, which is a security vulnerability.

In the login method, the JWT token is retrieved from the URL parameters using the getQueryString method. If a JWT token is provided, it is stored in the session using withSession("jwtToken" -> token). If no JWT token is provided, an Unauthorized response is returned.

The secureAction method retrieves the JWT token from the session. If a JWT token is present, a secure action is performed and an OK response is returned. If no JWT token is found in the session, an Unauthorized response is returned.

The vulnerability here is that the JWT token is sent via the URL parameters, which can be cached by the browser's history. This means that if an attacker has local access to the machine, they could retrieve the JWT token from the browser's history and use it to impersonate the user. This is a major security risk as it could lead to unauthorized access to sensitive user data.

Steps

  • Do not send sensitive information via URL parameters
  • Use HTTP POST method to send sensitive information
  • Store the JWT token securely on the server-side
  • Use secure session management techniques
  • Implement CSRF protection to prevent cross-site request forgery attacks

Compliant code

import play.api.mvc._
import play.api.libs.json._

object SessionController extends Controller {

case class LoginData(jwtToken: String)
implicit val loginDataReads = Json.reads[LoginData]

def login = Action(parse.json) { request =>
request.body.validate[LoginData].map { data =>
// Set the JWT token as a session variable
Ok("Logged in").withSession("jwtToken" -> data.jwtToken)
}.recoverTotal {
e => BadRequest("No JWT token provided")
}
}

def secureAction = Action { request =>
request.session.get("jwtToken").map { token =>
// Perform secure action
Ok("Secure action performed")
}.getOrElse {
Unauthorized("No JWT token in session")
}
}
}

The original code was vulnerable because it was sending the JWT token as a URL parameter. This is a security risk because URL parameters can be cached in the browsing history, making it possible for attackers with local access to the machine to obtain the token.

The fixed code no longer sends the JWT token as a URL parameter. Instead, it sends the token in the body of a HTTP POST request. This is done by changing the login action to parse JSON from the request body and extract the JWT token from it. The LoginData case class and its associated Reads instance are used to automatically convert the JSON into a Scala object.

The login action now returns a BadRequest response if the JWT token is not provided in the request body. This is done by using the recoverTotal method of the JsResult returned by validate. This method allows us to handle the case where the JSON validation fails, which would happen if the JWT token is not provided.

The secureAction remains the same. It retrieves the JWT token from the session and performs a secure action if the token is present. If the token is not present, it returns an Unauthorized response.

This code should be used in conjunction with secure session management techniques and CSRF protection to further enhance the security of the application.

References