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.