Uncontrolled external site redirect - Host Header Injection - Scala

Uncontrolled external site redirect - Host Header Injection - Scala

Need

Prevention of uncontrolled external site redirects through proper validation and sanitization of the Host header

Context

  • Usage of Scala for functional and object-oriented programming in the JVM environment
  • Usage of play.api.mvc for handling HTTP requests and responses in Play Framework

Description

Non compliant code

        import play.api.mvc._

object Application extends Controller {

  def redirect = Action { request =>
    val host = request.headers.get("Host").getOrElse("default.com")
    val destination = "http://" + host
    Redirect(destination)
  }
}
        
        

The above code is an example of a Scala backend application that uses the Play framework. The vulnerability lies in the redirect function, which takes a request and redirects the client to the URL specified by the "Host" header of the request.

The request.headers.get("Host").getOrElse("default.com") line of code is where the Host header is read from the incoming HTTP request. If there is no Host header present, it defaults to "default.com".

Then, the val destination = "http://" + host line creates a string that represents the destination URL for the redirect. The destination URL is constructed by concatenating "http://" with the value of the Host header.

Finally, the Redirect(destination) line sends a redirect response back to the client, which causes the client's browser to make a new request to the destination URL.

The vulnerability here is that the server blindly trusts the Host header from the client and uses it to construct the redirect destination. This is known as a Host Header Injection vulnerability. It allows an attacker to manipulate the Host header and cause the server to redirect the client to an arbitrary URL. This could be used for phishing attacks, where the attacker tricks the client into visiting a malicious website that looks like a legitimate one.

Steps

  • Validate the input: Ensure that the 'Host' header value is a valid and trusted domain.
  • Sanitize the input: Remove any special characters or unexpected characters from the 'Host' header value.
  • Whitelist allowed domains: Create a whitelist of trusted domains and only allow redirection to those domains.
  • Use a secure redirect method: Instead of using a simple redirect, use a secure redirect method provided by the framework that prevents host header injection.
  • Implement strict validation: Implement strict validation of the 'Host' header value to prevent any potential bypass attempts.
  • Implement rate limiting: Implement rate limiting to prevent abuse of the redirection functionality.
  • Keep the framework and dependencies up to date: Regularly update the Play framework and its dependencies to ensure any security patches or fixes are applied.

Compliant code

        import play.api.mvc._

object Application extends Controller {

  val allowedHosts = List("trusted.com", "secure.com") // Add your trusted domains here

  def redirect = Action { request =>
    val host = request.headers.get("Host").getOrElse("default.com")
    if (allowedHosts.contains(host)) {
      val destination = "http://" + host
      Redirect(destination)
    } else {
      BadRequest("Invalid host")
    }
  }
}
        
        

The updated code now includes a list of allowed hosts ( allowedHosts). This list should contain all the trusted domains that your application is allowed to redirect to.

In the redirect action, we first retrieve the 'Host' header from the request. If no 'Host' header is found, we default to "default.com".

Next, we check if the retrieved host is in our list of allowed hosts. If it is, we proceed with the redirection as before. If it's not, we return a "Bad Request" response.

This way, we ensure that our application only redirects to trusted domains, effectively mitigating the Host Header Injection vulnerability.

Remember to keep your list of allowed hosts up-to-date and as restrictive as possible to minimize the attack surface.

Also, consider implementing additional security measures such as input sanitization, strict validation, rate limiting, and regular updates to the Play framework and its dependencies.

References