TL;DR
The X-Frame-Options header is a security measure to prevent clickjacking attacks. However, it’s not foolproof and can be bypassed in certain situations. This guide explains common bypass techniques and how to mitigate them.
Understanding X-Frame-Options
The X-Frame-Options header tells the browser whether a page can be framed (embedded within another webpage). There are three main values:
- DENY: The page cannot be displayed in a frame, regardless of the site attempting to do so.
- SAMEORIGIN: The page can only be displayed in a frame if the origin (protocol, domain, and port) matches that of the top-level browsing context.
- ALLOW-FROM uri: The page can only be displayed in a frame from the specified URI. Note: This is largely unsupported by modern browsers due to security concerns.
Bypass Techniques
- Browser Compatibility Issues: Older browsers may not fully support or correctly interpret the
X-Frame-Optionsheader. Testing with multiple browser versions (including older ones) is crucial. - Header Manipulation via Proxies: If a user controls their proxy server, they can remove or modify the
X-Frame-Optionsheader before it reaches the browser. This is difficult to defend against directly but highlights the importance of other security layers. - JavaScript Frame Breaking (Limited Effectiveness): JavaScript can attempt to break out of a frame if detected. However, this is often unreliable and can be bypassed by attackers.
window.top.location = window.location;This attempts to redirect the top-level window to the current page’s URL, effectively breaking the frame.
- CSS Overlays: Attackers can use CSS to create an overlay on top of the legitimate content within a frame, tricking users into clicking malicious elements.
body { pointer-events: none; }This disables all mouse events on the framed page, allowing an attacker’s overlay to capture clicks.
- Redirection Exploits (with SAMEORIGIN): If a site uses
SAMEORIGINand has vulnerabilities that allow for open redirects, attackers can craft malicious URLs within the same origin to bypass the protection.- Attacker controls a page on the target domain.
- That page contains an open redirect vulnerability (e.g., using a parameter in the URL).
- The attacker crafts a malicious URL that redirects to their clickjacking payload after being framed by the vulnerable site.
- HTML5 History API Manipulation: In some cases, manipulating the browser’s history using
history.pushStateorhistory.replaceStatecan bypass frame detection mechanisms.window.history.pushState({}, '', '/');This changes the URL without reloading the page, potentially altering how the browser interprets the origin.
- Content Security Policy (CSP) Bypass: If a site uses a weak or misconfigured CSP, attackers can inject malicious scripts into the frame.
Inspect the
Content-Security-Policyheader for vulnerabilities.
Mitigation Strategies
- Use Subresource Integrity (SRI): SRI ensures that files loaded from CDNs or other sources haven’t been tampered with. This doesn’t directly prevent clickjacking but adds a layer of defense against malicious script injection.
<script src="https://example.com/script.js" integrity="sha384-..."></script> - Implement Frame Busting (with Caution): While JavaScript frame busting can be used, it’s not a reliable solution and can cause issues with legitimate use cases (e.g., widgets). If you must use it, consider using multiple techniques for broader compatibility.
<script>if(top != self) { top.location = self.location; }</script> - Content Security Policy (CSP): Implement a strong CSP that restricts the sources from which content can be loaded, including frames.
Content-Security-Policy: frame-ancestors 'self';This allows framing only from the same origin.
- X-Frame-Headers with Strict Enforcement: Ensure your server is correctly setting the
X-Frame-Optionsheader toDENYorSAMEORIGIN, and that it’s not being overridden by proxies. - Regular Security Audits & Penetration Testing: Regularly audit your website for vulnerabilities, including clickjacking risks.

