Web Security

Clickjacking

About 3 min read

What Is Clickjacking

Clickjacking is an attack technique that uses transparent or invisible iframes to overlay a legitimate web page on the user's screen, tricking the user into performing unintended click actions. Attacks that stack different content on top of a visible UI to mislead the user are collectively called UI redressing (UI spoofing), and clickjacking is its best-known form.

The attacker creates a trap page and overlays the target site on top of it using a transparent iframe. The user sees the buttons and links of the trap page, but what they actually click are elements of the target site within the transparent iframe. This allows actions like pressing "Like" buttons, changing settings, or approving transfers to be executed without the user's awareness.

How the Attack Works

Clickjacking is executed in the following steps.

  1. The attacker creates a trap web page with attractive content (video play button, game, sweepstakes form, etc.)
  2. The target site is loaded in an iframe and set to opacity: 0 (completely transparent) with CSS
  3. The transparent iframe is precisely positioned over the clickable elements of the trap page
  4. When the user clicks a button on the trap page, they actually click a button on the target site within the transparent iframe

Advanced Techniques

  • Drag & drop exploitation: Uses the user's drag operations to input data into forms within the transparent iframe
  • Cursor display spoofing: Replaces or hides the cursor image with CSS so that the apparent cursor position differs from the actual click position, making the user click somewhere they did not intend
  • Multi-step attacks: Guides multiple clicks, even getting the user to click the "OK" button on confirmation dialogs

When combined with XSS or CSRF, more complex attack scenarios can be constructed.

Implementing Defenses

The core of clickjacking defense is preventing your site from being embedded in another site's iframe.

CSP frame-ancestors Directive

The CSP frame-ancestors directive controls which parent page origins can embed your site in an iframe. It was introduced in CSP Level 2 as the successor to X-Frame-Options, and the CSP specification states that when both are present, frame-ancestors is applied and X-Frame-Options is ignored. If you are configuring this from scratch, this is the baseline.

  • frame-ancestors 'none': Does not allow iframe embedding on any site
  • frame-ancestors 'self': Allows embedding only from the same origin
  • frame-ancestors https://trusted.example.com: Allows embedding only from a specific origin

X-Frame-Options Header

Browser vendors introduced this as a non-standard header between 2009 and 2010, and it was documented in 2013 as RFC 7034 (Informational). There are two values you will actually use.

  • X-Frame-Options: DENY: Rejects all iframe embedding
  • X-Frame-Options: SAMEORIGIN: Allows embedding only from the same origin

The specification also defines a third value, ALLOW-FROM <URI>, but it does not work in major browsers, so do not use it. Browsers without support ignore the whole header, which leaves no protection at all.

The other pitfall is how SAMEORIGIN is matched. Many browsers compare only the origin of the top-level document, so a nested arrangement in which your page is loaded in an iframe on your own site and the whole thing is wrapped by an attacker page at the top level slips through. frame-ancestors checks each ancestor frame one by one, so it does not have this gap.

If you set both, browsers that support frame-ancestors apply that directive, and browsers that do not fall back to X-Frame-Options. Specifying both does not make them cancel each other out.

JavaScript Defense (Frame Busting)

A technique using scripts like if (top !== self) { top.location = self.location; } to escape to the top frame when loaded inside an iframe. However, since attackers can restrict JavaScript execution with the sandbox attribute, this should only be used as a supplement to HTTP header-based defenses.

Practical Countermeasure Checklist

A checklist for reliably implementing clickjacking countermeasures.

  • Verify security header configuration: Confirm that all page responses include X-Frame-Options: DENY (or SAMEORIGIN) and CSP frame-ancestors
  • Identify pages that need iframe embedding: For pages with legitimate reasons to allow iframes (such as payment form embedding), strictly limit the allowed origins
  • Protect critical operations: For critical operations like password changes, transfers, and account deletion, require re-authentication (password re-entry) in addition to CSRF tokens
  • Combine with HSTS: Enforce HTTPS and prevent security header removal through man-in-the-middle attacks
  • Regular testing: Regularly test whether your site can be embedded in an iframe. Verify using browser developer tools or security scanners

Clickjacking may not appear to cause major damage on its own, but combined with social engineering, it is a powerful attack technique that can execute critical operations without the user's awareness. Since it can be defended with just HTTP header configuration, it is a security measure with very high effectiveness relative to its implementation cost.

To learn more about this topic, see HTTP Security Headers: 5 Essential Headers to Protect Your Website.

Common Misconceptions

Clickjacking is an old attack technique and no longer a threat
The only precondition is that your site can be loaded in another site's iframe, so on pages that set neither X-Frame-Options nor CSP frame-ancestors the attack still works as of 2026. Any site with a UI where a single click finalizes a result (social media share buttons, OAuth authorization screens, settings toggles) needs to check its own response headers, no matter when the site was launched.
JavaScript frame busting alone is sufficient defense
Attackers can restrict JavaScript execution with the iframe's sandbox attribute or block frame escape with the onbeforeunload event. HTTP header-based defense (X-Frame-Options, CSP frame-ancestors) is essential, and JavaScript is only a supplementary measure.
Share

Related Terms

Related Articles