askvity

How to Prevent Your Website From Being Displayed in an Iframe Using Content Security Policy (CSP)

Published in Web Security 6 mins read

The most effective way to prevent your website content from being displayed within an iframe on another site – a technique often used in clickjacking attacks – is by implementing security policies through HTTP headers. This method doesn't technically "disable" the iframe HTML tag itself but rather instructs browsers not to load your content when it's framed by another origin.

Why Prevent Framing?

Preventing your site from being displayed in an iframe is a crucial security measure. It primarily protects against clickjacking, an attack where a malicious site loads your page in a transparent iframe overlaid on their own page. Users interacting with what they think is the malicious page are unknowingly clicking on elements within your framed site.

The Primary Method: Content Security Policy (CSP)

Content Security Policy (CSP) is a powerful security standard that helps prevent various types of attacks, including clickjacking. By adding a Content-Security-Policy HTTP header to your web server's responses, you can control how your page loads resources and, importantly, whether it can be framed.

The reference information highlights this approach:

  1. Add a Content Security Policy (CSP) header to your website's HTTP response.
  2. Set the frame-src directive to 'none' disallow iframes.
  3. Test your site thoroughly to ensure that the CSP policy does not break any legitimate functionality.

While the reference specifically mentions frame-src 'none', it's important to clarify the role of different CSP directives related to framing:

  • frame-ancestors: This is the correct directive to prevent your page from being framed by other sites. Setting frame-ancestors 'none' tells the browser no site is allowed to put your page in an iframe, frame, object, embed, or applet.
  • frame-src: This directive controls the sources that can be loaded within iframes, frame, object, embed, or applet elements on your own page. Setting frame-src 'none', as mentioned in the reference, prevents any iframes on your page from loading content from any source. This effectively "disables" the functionality of iframes you might place on your own page, but it does not prevent external sites from framing your page.

Therefore, to prevent being framed by other sites, you should use frame-ancestors 'none'.

Implementing CSP frame-ancestors

You typically add CSP headers via your web server configuration (e.g., Apache, Nginx, IIS) or in your application code. Adding it via an HTML <meta> tag is generally not recommended for framing directives like frame-ancestors because the browser needs to know the policy before rendering the page, which can happen too late with a meta tag.

Here's how you might add the header:

  • Apache:
    Header always set Content-Security-Policy "frame-ancestors 'none';"
  • Nginx:
    add_header Content-Security-Policy "frame-ancestors 'none';";

This header instructs the browser that the page cannot be framed by any source.

Steps for Implementation (Incorporating Reference Points)

Based on the reference and best practices, here are the steps to prevent your site from being framed:

  1. Choose the Right Directive: Decide whether you need to prevent being framed (frame-ancestors) or prevent iframes on your page from loading content (frame-src). For clickjacking protection (preventing being framed), use frame-ancestors.
  2. Add the CSP Header: Configure your web server or application to include the Content-Security-Policy HTTP header with the chosen directive and value (e.g., frame-ancestors 'none';).
  3. Test Thoroughly: This is crucial, as stated in the reference. After implementing the policy, test your website extensively. Ensure that legitimate uses of framing (if any, e.g., within your own domain for specific purposes, which would require frame-ancestors 'self') are not broken. Check different browsers, as CSP support can vary slightly. Monitor your browser's developer console for any CSP violation reports.

You can also use frame-ancestors 'self' if you only want to allow framing from pages within your own domain.

Older Method: X-Frame-Options Header

Before CSP became widely supported, the X-Frame-Options HTTP header was the standard way to prevent clickjacking. It's still a good idea to include this header for compatibility with older browsers that might not fully support CSP's frame-ancestors.

Common values for X-Frame-Options:

  • DENY: Prevents any domain from framing the page.
  • SAMEORIGIN: Allows framing only if the page attempting to frame is from the same origin as the page being framed.
  • ALLOW-FROM uri: (Older and less supported) Allows framing only from a specified URI.

You can add this header alongside your CSP header. For example:

  • Apache:
    Header always set X-Frame-Options "DENY"
    Header always set Content-Security-Policy "frame-ancestors 'none';"
  • Nginx:
    add_header X-Frame-Options "DENY";
    add_header Content-Security-Policy "frame-ancestors 'none';";

If both X-Frame-Options and CSP frame-ancestors are present, and they conflict, the browser should ideally prioritize CSP, but including both provides broader protection.

Which Method Should You Use?

Feature Content-Security-Policy (CSP) frame-ancestors X-Frame-Options
Modernity Current standard, flexible Older, less flexible
Specificity Controls various framing types (iframe, frame, etc.) Primarily iframe, frame
Flexibility Allows specifying multiple allowed origins/schemes (though 'none' or 'self' are common for denial) Limited options (DENY, SAMEORIGIN)
Browser Support Good in modern browsers Excellent, including older browsers
Recommendation Preferred method Good for backward compatibility

For maximum protection against being framed, it's recommended to implement the Content-Security-Policy header with the frame-ancestors 'none'; directive and, optionally, include the X-Frame-Options: DENY header for broader browser support.

These methods effectively prevent your site from loading when embedded in an iframe on another site, providing a strong defense against clickjacking.

Related Articles