Skip to main content

Lack of data validation - Reflected Parameters

Need

Implementation of proper input validation and sanitization

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
  • Usage of play.api.mvc.ControllerComponents for building controllers in Play Framework
  • Usage of play.api.mvc.BaseController for creating controllers in Play Framework
  • Usage of play.api.mvc.Action for handling HTTP requests in Play Framework
  • Usage of play.api.mvc.Request for handling HTTP requests in Play Framework
  • Usage of play.api.mvc.AnyContent for handling various types of HTTP request content in Play Framework
  • Usage of play.api.mvc.Result for handling HTTP responses in Play Framework
  • Usage of play.api.mvc.Results.Ok for returning a successful HTTP response in Play Framework

Description

Non compliant code

import play.api.mvc._

class HomeController @Inject()(val controllerComponents: ControllerComponents) extends BaseController {

def index(name: String) = Action { implicit request: Request[AnyContent] =>
Ok("Hello " + name)
}
}

In the above Scala code, we have a simple Play framework controller named HomeController. This controller has a single action method named index that takes a string parameter name and returns a 200 OK HTTP response with a message "Hello " concatenated with the name parameter.

The name parameter is directly used in the response without any form of validation or sanitization. This is a security vulnerability because an attacker can pass malicious scripts as the name parameter. Since the server echoes back the input without sanitizing it, the malicious script will be executed in the user's browser when the response is rendered. This is a classic example of a Reflected Cross-Site Scripting (XSS) vulnerability.

For example, an attacker can send a request like /index?name=<script>malicious_code_here</script> and the server will return "Hello <script>malicious_code_here</script>", which will execute the malicious script in the user's browser if the response is rendered as HTML.

The vulnerability can be fixed by validating and sanitizing the name parameter before using it in the response.

Steps

  • Implement input validation to sanitize and validate the 'name' parameter.
  • Use a whitelist approach to allow only specific characters or patterns in the input.
  • Apply encoding or escaping techniques to prevent special characters from being interpreted as code.
  • Consider using a library or framework-provided validation mechanism to simplify the validation process.
  • Handle validation errors gracefully and provide appropriate error messages to the user.
  • Regularly update and patch the application and its dependencies to stay protected against known vulnerabilities.

Compliant code

import play.api.mvc._
import play.api.data._
import play.api.data.Forms._

class HomeController @Inject()(val controllerComponents: ControllerComponents) extends BaseController {

val nameForm: Form[String] = Form(
"name" -> text.verifying("Invalid name!", name => name.matches("^[a-zA-Z0-9]*$"))
)

def index = Action { implicit request: Request[AnyContent] =>
nameForm.bindFromRequest.fold(
formWithErrors => {
// binding failure, you retrieve the form containing errors:
BadRequest("Invalid input!")
},
nameData => {
/* binding success, you get the actual value. */
Ok("Hello " + nameData)
}
)
}
}

The above code fixes the vulnerability by adding data validation to the 'name' parameter.

The nameForm is a form that contains a single field 'name'. This field is a text field that is verified using a regular expression. The regular expression ^[a-zA-Z0-9]*$ allows only alphanumeric characters. If the input does not match this pattern, the form binding will fail and an error message "Invalid name!" will be returned.

The index method now uses the nameForm to bind the request data. If the form binding is successful, it means that the input is valid and the method proceeds as before. If the form binding fails, it means that the input is invalid and the method returns a BadRequest with the message "Invalid input!".

This way, the code ensures that only valid input is processed, preventing special characters from being interpreted as code and thus mitigating the risk of XSS attacks.

Remember to handle validation errors gracefully and provide appropriate error messages to the user. Regularly update and patch the application and its dependencies to stay protected against known vulnerabilities.

References