Web security

Clickjacking

Definition

Clickjacking means displaying a legitimate site in an invisible frame layered over a booby-trapped page: the victim thinks they are clicking a harmless button but actually triggers an action on the hidden site, with their own session. The frame-ancestors and X-Frame-Options headers prevent it.

Clickjacking, Web security

It is also known as a “UI redressing” attack. MITRE classifies it as CWE-1021: the site doesn't restrict, or improperly restricts, being rendered inside frames that belong to another domain. There is no injected code and no stolen password here: the attacker hijacks a click the victim makes themselves, with their own session.

How clickjacking works

The attacker creates a page that displays something enticing: a game, a “Continue” button, a fake verification. On top of it, they load the target site in an <iframe> made invisible (zero opacity) and place the site's sensitive button exactly under the fake one. If the browser attaches the session cookies to that frame, the logged-in victim triggers the real action: changing an email address, confirming a setting, granting access.

The four layers of a clickjacking attack: a visible decoy page with a button that lures the click, an invisible frame containing the legitimate site with its sensitive button lined up under the cursor, the victim's session that gives the action its rights if the browser attaches the cookies, and the site's defense with frame-ancestors self or X-Frame-Options SAMEORIGIN, which prevents display in the frame
Without a header that forbids framing, any site can layer yours over its own page.
Video: “What is Clickjacking?” (Hacksplaining)

How to protect against it

The protection is simple and relies on the browser: the site states in its HTTP security headers who is allowed to display it in a frame.

  • Content-Security-Policy: frame-ancestors: the modern directive of the Content Security Policy. 'none' forbids any framing, 'self' only allows the site itself, and you can list specific origins. It is not honored in a <meta> tag: it must be sent as an HTTP header.
  • X-Frame-Options: the older header, still useful for older browsers. It accepts DENY or SAMEORIGIN; the ALLOW-FROM value is obsolete and ignored by modern browsers.

When both are present, the CSP specification says to ignore X-Frame-Options in favor of frame-ancestors; sending both is still recommended. JavaScript “frame-busting” scripts, on the other hand, are easy to bypass and are not enough. SameSite cookies also reduce the risk, without preventing framing. Finally, a recent variant, “double clickjacking,” relies on successive windows rather than a frame: headers don't block it, which is why server-side confirmation is worthwhile for the most sensitive actions.

For WordPress

WordPress already protects its sensitive screens: the send_frame_options_header() function, called on the login page and in the admin area, sends X-Frame-Options: SAMEORIGIN and, in current versions, frame-ancestors 'self'. Public pages, however, get nothing by default. Yet that is where a store's customer account area or profile forms live. You can add the header at the server level, for example in an .htaccess file on Apache:

<IfModule mod_headers.c>
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set Content-Security-Policy "frame-ancestors 'self'"
</IfModule>

Watch out for an existing CSP: two Content-Security-Policy headers are combined, so the directive should then be added to the existing policy. On Nginx, the equivalent is add_header X-Frame-Options SAMEORIGIN always;. If you'd rather not touch the server configuration, WP Masquerade Pro's security headers send X-Frame-Options: SAMEORIGIN by default across the whole site, without overwriting a header that is already set, while keeping your posts embeddable in other WordPress sites through oEmbed. Our guide to security headers covers the other useful headers and how to test them.

Further reading

  • Article How to set up HTTP security headers on WordPress: CSP, HSTS and the rest
  • Page WordPress security headers

Sources

  1. OWASP Cheat Sheet Series: Clickjacking Defense (external link, opens in a new tab)
  2. MDN: CSP frame-ancestors (external link, opens in a new tab)
  3. MDN: X-Frame-Options (external link, opens in a new tab)
  4. WordPress Developer Resources: send_frame_options_header() (external link, opens in a new tab)

All definitions

WordPress security, without the noise

One e-mail when something matters: new attacks seen in the wild, plugin updates and practical guides. No spam, unsubscribe in one click.

Start free, go Pro when you’re ready

The free version already hides WordPress and moves the login page. Pro adds aliases, two-factor authentication and monitoring.