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.