logo

Sensitive information sent via URL parameters - Session - Scala


Need

Secure transmission of sensitive information in session tokens


Context

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

Description

Insecure Code Example

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

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

Secure Code Example

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

  • 276 - Sensitive information sent via URL parameters - Session

  • Last updated

    2023/09/18