Glossary

Clickjacking

Clickjacking is an attack in which a page is loaded invisibly in a frame over an attacker's own content, so that a visitor who believes they are clicking one thing actually clicks something on the hidden page. Because the framed page is loaded in the visitor's own browser with their own session, the click is fully authenticated. The defence is not in the application logic: it is a response header refusing to be framed.

How the attack is constructed

The attacker builds a page with attractive content — a game, a video, a prize.

The target page is loaded in an iframe positioned over it, made transparent with CSS opacity and aligned so that a specific control sits under whatever the visitor is invited to click.

The visitor clicks. The click is delivered to the framed page, which is the real site with the real session.

Variants replace the click with a drag, a keystroke sequence, or a sequence of clicks that completes a multi-step flow.

Nothing about the target site is compromised. The attack is entirely in how it is embedded.

What is worth stealing a click for

Anything one click completes: a follow, a like, a permission grant, an authorisation approval, a purchase with saved payment details.

Permission prompts — camera, microphone, notifications — where a click grants access that persists.

Administrative actions on a system where the victim is a privileged user.

Authorisation screens in delegated login flows, where a click grants an application access to an account.

The defences that work

`Content-Security-Policy: frame-ancestors 'none'` or `'self'`, which tells the browser to refuse the embedding outright. This is the current mechanism.

`X-Frame-Options: DENY` or `SAMEORIGIN`, the older header, kept alongside for clients that predate CSP support.

JavaScript frame-busting scripts were the historical approach and are defeated by sandboxed iframes. They should not be relied on.

For high-consequence actions, requiring a second step that cannot be completed blindly — re-entering a password, confirming a code — removes the single-click premise the attack depends on.

`SameSite` cookies help indirectly: a framed page loaded cross-site without its session cookie is not logged in, so the stolen click has no authority behind it.

How to test a page

Create a local HTML file with an iframe pointing at the page and open it. A protected page refuses, and the console names the header responsible.

Check response headers with `curl -I` for both `X-Frame-Options` and a `frame-ancestors` directive in the policy.

Test authenticated pages specifically, since those are the ones with something to steal and are frequently served by a different route than the public site.

Check that pages intended to be embeddable have an explicit, narrow `frame-ancestors` list rather than no protection at all.

Remember that the visitor sees nothing unusual. There is no visual artefact to notice and no log entry that distinguishes a stolen click from a real one, which is why the defence has to be preventive.

Frequently asked questions

Which header stops clickjacking?
Content-Security-Policy frame-ancestors, with X-Frame-Options kept alongside for older clients. Both instruct the browser to refuse the embedding.
Do frame-busting scripts work?
Not reliably. A sandboxed iframe can prevent the script from navigating the top window, which defeats the technique.
Does my marketing site need this?
It has less to lose than an authenticated application, but a site-wide SAMEORIGIN costs nothing and removes the question.

Sources

Related

VeriFixScan crawls a site and applies its checks to every page it reaches, keeping the evidence behind each finding. Scanning one website is free.

Scan a website