Skip to main content

Business information leak - Token

Need

Protection of sensitive user information in session tokens

Context

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

Description

Non compliant code

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

case class User(username: String, email: String, fullName: String)

object UserController extends Controller {
def login = Action { request =>
val user = User("testUser", "[email protected]", "Test User")
val userJson = Json.toJson(user)
val token = java.util.Base64.getEncoder.encodeToString(userJson.toString.getBytes)
Ok("Logged in!").withSession("session" -> token)
}
}

In the above Scala code, we have a User case class that contains a username, email, and full name of the user. We have a UserController object that extends the Controller class provided by the Play framework and it has a login method.

The login method is creating a User object with some hardcoded values, then it converts this user object into a JSON string using the Json.toJson method provided by the Play framework.

After that, the JSON string is encoded into a Base64 string to create a token. This token is then stored in the session using the withSession method provided by the Play framework.

The vulnerability here is that the token, which is stored in the session and can be accessed by the client, contains sensitive user information such as the username, email, and full name. This can lead to a business information leak if the token is intercepted or accessed by an unauthorized entity.

Steps

  • Do not include sensitive information in the session token.
  • Instead, store the sensitive information in a secure server-side storage, such as a database.
  • When generating the session token, only include a unique identifier or reference to the user's session.
  • Ensure that the session token is securely generated and cannot be easily guessed or tampered with.
  • When retrieving the session token, use the unique identifier or reference to retrieve the user's sensitive information from the secure storage.
  • Avoid storing the session token in plain text. Instead, consider using encryption or hashing to protect the token's integrity.
  • Regularly review and update the security measures in place to protect the session token and sensitive user information.

Compliant code

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

case class User(username: String, email: String, fullName: String)

object UserController extends Controller {
def login = Action { request =>
val user = User("testUser", "[email protected]", "Test User")
val userId = java.util.UUID.randomUUID().toString
// Store user data in a secure server-side storage
// For the purpose of this example, we will just use a simple Map
val userStorage = scala.collection.mutable.Map[String, User]()
userStorage += (userId -> user)
Ok("Logged in!").withSession("session" -> userId)
}
}

The updated code no longer includes sensitive user information in the session token. Instead, it generates a unique identifier for each user session using java.util.UUID.randomUUID().toString. This unique identifier is then used as a key to store the user's information in a secure server-side storage. In this example, we use a simple mutable Map as the server-side storage for simplicity, but in a real-world application, this should be a secure database or other secure storage mechanism.

When the user logs in, the server sends back only the unique identifier in the session token. The server can then use this identifier to retrieve the user's information from the secure storage when needed. This way, even if an attacker manages to get hold of the session token, they will not be able to extract any sensitive user information from it.

This approach also has the advantage of making the session token more secure. Since the token is now a randomly generated UUID, it is much harder for an attacker to guess or tamper with it.

Finally, it's important to note that the session token should not be stored in plain text. In a real-world application, you should consider using encryption or hashing to protect the integrity of the token. Regularly reviewing and updating your security measures is also crucial to ensure the ongoing protection of your session tokens and user information.

References