Deep DivesClickjacking

Clickjacking

One-line relationship: clickjacking steals a click, not a request or a credential. It belongs to C3 (browser-side security) alongside CSRF, but the mechanism and the defense are both completely different — don’t conflate them.

What it is

An attacker loads your authenticated page inside an invisible or near-transparent <iframe> on their own site, then overlays a decoy — “click here to claim your prize” — positioned exactly over a real, sensitive button underneath (a “confirm transfer” button, say). The user thinks they’re clicking the decoy; they’re actually clicking the real page they didn’t know was there. Because the iframe carries the victim’s real, authenticated session, the click is completely genuine from the bank’s point of view — there’s no forged request to detect, no stolen token, just a real user clicking a real button they couldn’t see.

Try it

The grey checkerboard is attacker.example, framing your bank page beneath a decoy "Claim your prize" layer at ~40% opacity. Click the decoy button — you're really clicking whatever sits at that exact pixel in the frame underneath.

🎉 Click here to claim your prize!
The lesson: clickjacking doesn't forge a request the way CSRF does — it tricks a real, authenticated user into making a real click on a page they can't see. The defense is declarative and server-side: Content-Security-Policy: frame-ancestors (or the older X-Frame-Options) tells the browser which origins, if any, are allowed to frame the page. Set it to 'none' or a specific list and the attacker's iframe never renders your content at all.

The defense — deny framing, declaratively

The fix doesn’t try to detect the overlay; it prevents the page from being embedded at all:

  • Content-Security-Policy: frame-ancestors 'none' (or a specific allowlist) — the modern, preferred mechanism.
  • X-Frame-Options: DENY (or SAMEORIGIN) — the older header, still worth sending for browsers that don’t honor frame-ancestors.

Both are response headers set by the page being protected — there’s no client-side JavaScript defense that’s reliable, because “frame-busting” scripts can themselves be neutralized by a determined attacker (e.g. the sandbox attribute on the attacker’s iframe can strip script execution while still rendering the frame).

Clickjacking vs CSRF

Both live in C3 and both exploit an ambient authenticated session, but the mechanism differs:

ClickjackingCSRF
What’s forgedNothing — a real clickA request, forged and auto-submitted
What the user doesClicks, thinking they’re doing something elseNothing — a hidden form submits itself
Defenseframe-ancestors / X-Frame-OptionsSameSite cookies, anti-CSRF tokens

See CSRF for the request-forgery half.

What to take to the client

This is a two-line header fix with no functional trade-off for a page that’s never meant to be framed by a third party (which is essentially every authenticated banking screen). There’s no reason for it to be missing, and it’s one of the first things a pentest or an ASVS review checks.