Insecure or unset HTTP headers - CORS - Scala

Insecure or unset HTTP headers - CORS - Scala

Need

Secure and properly configure HTTP headers for Cross-Origin Resource Sharing (CORS)

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._

class ApplicationController extends Controller {

  def index = Action { request =>
    Ok("Hello World").withHeaders(
      "Access-Control-Allow-Origin" -> "*",
      "Access-Control-Allow-Methods" -> "OPTIONS, GET, POST, PUT, DELETE, HEAD", 
      "Access-Control-Allow-Headers" -> "Accept, Content-Type, Origin, X-Json, X-Prototype-Version, X-Requested-With",
      "Access-Control-Allow-Credentials" -> "true"
    )
  }
}
        
        

The above code is a simple controller in a Scala Play application. The index action is returning a response with a set of headers that define Cross-Origin Resource Sharing (CORS) policies.

The vulnerability lies in the "Access-Control-Allow-Origin" -> "*" line. The "*" is a wildcard that allows any origin to access the resource. This is insecure because it means that any website can make a request to this server and get a response. In a real-world application, this could potentially expose sensitive data to malicious actors.

The other headers "Access-Control-Allow-Methods" and "Access-Control-Allow-Headers" are also potentially insecure if they allow more methods or headers than necessary for the application to function correctly.

Lastly, the header "Access-Control-Allow-Credentials" -> "true" allows the response to be shared with frontend JavaScript code when the request's credentials mode (Request.credentials) is 'include'. When used in response to a preflight request, this indicates whether or not the actual request can be made using credentials. This can lead to potential security risks if misused.

Steps

  • Remove the wildcard (*) from the 'Access-Control-Allow-Origin' header and specify the allowed domains explicitly.
  • Review and update the 'Access-Control-Allow-Methods' header to include only the necessary HTTP methods for your application.
  • Remove any unnecessary headers from the 'Access-Control-Allow-Headers' header.
  • Consider using a whitelist approach for the 'Access-Control-Allow-Headers' header to only allow specific headers.
  • Evaluate if 'Access-Control-Allow-Credentials' header is necessary for your application. If not, remove it.
  • Implement proper validation and sanitization of the allowed domains, methods, and headers to prevent any potential security risks.

Compliant code

        import play.api.mvc._

class ApplicationController extends Controller {

  def index = Action { request =>
    Ok("Hello World").withHeaders(
      "Access-Control-Allow-Origin" -> "http://example.com", // specify your domain here
      "Access-Control-Allow-Methods" -> "GET, POST", // specify only necessary methods
      "Access-Control-Allow-Headers" -> "Accept, Content-Type, Origin", // specify only necessary headers
      "Access-Control-Allow-Credentials" -> "true" // evaluate if this is necessary
    )
  }
}
        
        

The original code had a vulnerability in the HTTP headers related to Cross-Origin Resource Sharing (CORS). The 'Access-Control-Allow-Origin' header was set to '*', which means that it would accept requests from any domain. This is a security risk as it allows any website to make a request to your server and access its resources.

The fixed code now specifies a particular domain in the 'Access-Control-Allow-Origin' header. This means that only requests from this domain will be accepted. You should replace 'http://example.com' with the actual domain that should be allowed to access your server.

The 'Access-Control-Allow-Methods' header was also updated to include only the necessary HTTP methods for your application. In this case, only 'GET' and 'POST' requests are allowed. You should review this and include only the methods that your application needs.

The 'Access-Control-Allow-Headers' header was updated to include only necessary headers. This reduces the attack surface by limiting the headers that can be included in a request.

The 'Access-Control-Allow-Credentials' header is still included in the response. This header indicates whether the response to the request can be exposed when the credentials flag is true. You should evaluate if this is necessary for your application. If it's not, you should remove this header.

Remember to implement proper validation and sanitization of the allowed domains, methods, and headers to prevent any potential security risks.

References