Skip to main content

Insecure or unset HTTP headers - X-Frame Options

Need

Implementation of secure and properly configured HTTP headers

Context

  • Usage of Scala 2.12 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 { implicit request =>
Ok(views.html.index("Your new application is ready.")).withHeaders(
"X-Frame-Options" -> "SAMEORIGIN"
)
}
}

The above code snippet is an example of a controller in a Play framework application. In the index action, it responds with an Ok status and renders an HTML view. Along with this response, it sets the HTTP header X-Frame-Options to SAMEORIGIN.

The X-Frame-Options header is a security measure that can be used to indicate whether or not a browser should be allowed to render a page in a <frame>, <iframe>, <embed> or <object> . The SAMEORIGIN directive means that the page can only be displayed in a frame on the same origin as the page itself.

However, the X-Frame-Options header is considered deprecated and its protection can be bypassed using several iframe layers. This vulnerability can lead to clickjacking attacks where an attacker tricks a user into clicking a concealed link.

In the context of this code, the application uses the X-Frame-Options header as the only protection mechanism against clickjacking, which makes it vulnerable to such attacks.

Steps

  • Replace the use of X-Frame-Options header with Content-Security-Policy header.
  • Set the Content-Security-Policy header to include the 'frame-ancestors' directive with the 'self' value.
  • Ensure that the Content-Security-Policy header is set on all server responses.
  • Test the application to verify that the clickjacking vulnerability is fixed.

Compliant code

import play.api.mvc._

class ApplicationController extends Controller {
def index = Action { implicit request =>
Ok(views.html.index("Your new application is ready.")).withHeaders(
"Content-Security-Policy" -> "frame-ancestors 'self'"
)
}
}

The previous code was vulnerable to clickjacking attacks because it was using the deprecated X-Frame-Options header as the only protection mechanism. This header can be bypassed using several iframe layers, making it an insecure method of protection.

The updated code replaces the X-Frame-Options header with the Content-Security-Policy header. This header is more secure and is currently recommended for protection against clickjacking attacks.

The Content-Security-Policy header is set to include the frame-ancestors directive with the 'self' value. This means that the application will only allow iframes from the same origin to embed its pages, effectively preventing clickjacking attacks.

This change should be applied to all server responses to ensure consistent protection across the application.

After applying this change, it's recommended to test the application to verify that the clickjacking vulnerability is fixed. This can be done by trying to embed the application's pages in an iframe from a different origin and verifying that the browser blocks the attempt.

References