Skip to main content

Insecure or unset HTTP headers - X-Frame Options

Need

Implementation of secure and properly configured HTTP headers

Context

  • Usage of Ruby 2.0+ for developing Ruby applications
  • Usage of Rails for building web applications in Ruby

Description

Non compliant code

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
after_action :set_headers

private

def set_headers
response.headers["X-Frame-Options"] = "SAMEORIGIN"
end
end

In the above code, the application sets the X-Frame-Options HTTP header to SAMEORIGIN in every response from the server. This is done in the ApplicationController, which is the superclass of all other controllers in a Rails application. The after_action callback is used to ensure that the set_headers method is called after every action in every controller.

The X-Frame-Options HTTP header is a security measure that prevents the browser from displaying the contents of a web page in a <frame>, <iframe>, <embed>, or <object> HTML element, unless the web page belongs to the same origin as the web page that includes the HTML element. This is intended to provide some protection against 'clickjacking' attacks.

However, the X-Frame-Options header is considered deprecated because its protection can be bypassed using several iframe layers. Therefore, relying on this header as the only protection mechanism against clickjacking is a security vulnerability.

A more robust solution would be to use the Content-Security-Policy header with the frame-ancestors directive, which provides a more powerful and flexible way to control which web pages can be displayed in frames.

In addition, it is also recommended to use other security measures, such as ensuring that all user input is properly validated and sanitized, using anti-CSRF tokens, and implementing proper session management.

Steps

  • Replace the use of X-Frame-Options header with Content-Security-Policy header.
  • Set the Content-Security-Policy header to include 'frame-ancestors' directive with the 'self' value.
  • Ensure that the 'frame-ancestors' directive does not allow any other domains to frame the application.
  • Consider implementing additional security measures to prevent clickjacking attacks.

Compliant code

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
after_action :set_headers

private

def set_headers
response.headers["Content-Security-Policy"] = "frame-ancestors 'self'"
end
end

The updated code replaces the deprecated X-Frame-Options header with the Content-Security-Policy header. The Content-Security-Policy header is a more modern and flexible solution for controlling content loading and preventing attacks such as clickjacking.

The frame-ancestors 'self' directive is used to specify that only the same origin can embed the application in a frame. This means that no other domains can frame your application, providing a stronger protection against clickjacking attacks.

This change is a part of a broader strategy to enhance the security of your application. It's recommended to implement additional security measures, such as regularly updating and patching your software, using secure coding practices, and educating your users about the risks of clickjacking and other attacks.

References