Enforce strict data validation and trust boundaries
import play.api.mvc._
import play.api.libs.json._
class ApplicationController(cc: ControllerComponents) extends AbstractController(cc) {
def saveData = Action(parse.json) { request =>
val value = (request.body \\ "data").as[String]
val trustedData = "This is trusted data"
val mixedData = trustedData + value
Ok("Data received: " + mixedData)
}
}
In the above Scala code, we have a Play Framework controller
ApplicationController
with a method
saveData
that accepts JSON data from the HTTP request.
The vulnerability lies in the
saveData
method. This method extracts data from the JSON request body without validating it and mixes it with trusted data. Here,
(request.body \\ "data").as[String]
extracts the "data" field from the JSON request body and treats it as a string. This extracted data is considered untrusted as it comes from the client and can potentially contain malicious input.
The trusted data is defined as
val trustedData = "This is trusted data"
. The untrusted data (extracted from the request) and the trusted data are then mixed together in
val mixedData = trustedData + value
.
The problem with this code is that it doesn't validate or sanitize the untrusted data before mixing it with the trusted data. This could lead to a variety of security vulnerabilities such as Cross-Site Scripting (XSS), SQL Injection, or Command Injection depending on how the mixed data is used later in the application. In this case, the mixed data is directly sent back to the client which could lead to Reflected XSS if the untrusted data contains a malicious script.
import play.api.mvc._
import play.api.libs.json._
class ApplicationController(cc: ControllerComponents) extends AbstractController(cc) {
def saveData = Action(parse.json) { request =>
val value = (request.body \\ "data").asOpt[String]
val trustedData = "This is trusted data"
value match {
case Some(untrustedData) if validateData(untrustedData) =>
val sanitizedData = sanitizeData(untrustedData)
val mixedData = trustedData + sanitizedData
Ok("Data received: " + mixedData)
case _ => BadRequest("Invalid data")
}
}
def validateData(data: String): Boolean = {
// Implement your validation logic here
true
}
def sanitizeData(data: String): String = {
// Implement your sanitization logic here
data
}
}
The updated code separates trusted and untrusted data into different variables. The untrusted data is extracted from the request body and is validated and sanitized before it is used.
The
validateData
function is used to check if the untrusted data meets the expected format and constraints. If the data is invalid, a
BadRequest
response is returned. This function should be implemented with the specific validation logic for the application.
The
sanitizeData
function is used to clean the untrusted data to ensure it does not contain any malicious content. This function should be implemented with the specific sanitization logic for the application.
The trusted and sanitized untrusted data are then combined and returned in the response. This ensures that the data integrity and trust boundaries are maintained.