Clickjacking is a UI redressing attack in which an attacker overlays a legitimate page on top of a deceptive facade so that the victim believes she is clicking an innocuous element when she is actually triggering a sensitive action in another application where she holds an active session. The technique does not exploit a memory bug or steal the cookie: it manipulates what the user sees against what the browser executes. The click is real, but its destination has been hijacked through invisible layers, usually a transparent iframe positioned over a decoy button.
The essentials. Clickjacking abuses the user's visual trust, not a server bug. The attacker frames the victim application in an iframe with zero opacity and aligns it over a bait. Modern defenses rely on three layers: the
X-Frame-Optionsheader, theContent-Security-Policy: frame-ancestorsdirective, andSameSite=LaxorStrictcookies that break the cross site session. The flaw is catalogued as CWE-1021 (Improper Restriction of Rendered UI Layers or Frames).
What clickjacking is: the UI redressing mechanism
The term was coined by Jeremiah Grossman and Robert Hansen in 2008, and since then it has designated an entire family of interface redressing attacks. The base pattern needs three pieces operating at once: a victim with an active session in the target application, an application that allows itself to be embedded in a third party iframe, and an attacker page that loads that iframe invisibly over a visible lure.
The first step is framing the target. The attacker inserts the victim application inside an <iframe> on its own site. If the target does not restrict framing, the browser renders it normally, including the victim's session cookie, because the iframe loads the real domain with the credentials the browser already has stored.
The second step is hiding the real layer. Through CSS (opacity: 0, a high z-index and absolute positioning) the iframe becomes transparent yet stays above the visible content. The user sees an apparently normal page (a button promising a prize, a video player, a fake captcha) while the target's sensitive element sits aligned right under the cursor.
The third step is harvesting the click. When the victim presses the lure, the click passes through the transparent layer and lands on the real framed button: accepting a permission, confirming a payment, publishing content or authorising an OAuth application. The server receives a legitimate action, with a valid session and a real human gesture, and has no trivial way to know that the user was deceived about what she was clicking.
Technical example: the invisible iframe
The skeleton of a clickjacking proof of concept fits in a few lines. It is shown for didactic and defensive auditing purposes.
<style>
iframe {
position: absolute;
top: -8px; left: -8px;
width: 500px; height: 400px;
opacity: 0.0; /* the real layer is invisible */
z-index: 2;
}
#bait {
position: absolute;
top: 300px; left: 120px;
z-index: 1; /* sits beneath the iframe */
}
</style>
<button id="bait">Play video</button>
<iframe src="https://victim-app.tld/account/delete"></iframe>
By adjusting the coordinates, the victim application's real button (for example, confirming account deletion) is placed exactly over the "Play video" bait. The victim believes she is starting a video and actually confirms a destructive action. Reproducing it in a controlled lab (an iframe pointing at DVWA or an in house environment) confirms in seconds whether the target allows framing.
Clickjacking variants
Likejacking
This is the variant that popularised the attack at scale. A social network's "Like" or share button is invisibly framed over attractive content. Each user click propagates a link on their timeline without them noticing, and that viral spread drags new victims toward the same trap.
Cursorjacking
Instead of moving the click destination, cursorjacking manipulates the perception of the cursor. The attacker hides the real pointer with CSS and draws a fake cursor offset by a few pixels. The user believes she is aiming at one spot on the screen, but the effective click lands elsewhere, aligned with the framed sensitive element.
Drag-and-drop and filejacking
Some variants depend not on the click but on dragging. Through drag-and-drop gestures the victim is forced to extract text from a framed widget (for example, a visible token) and drop it into a field controlled by the attacker, or to interact with file selectors to exfiltrate local paths.
Tapjacking on mobile
On Android, the equivalent is known as tapjacking: a malicious app draws an overlay (SYSTEM_ALERT_WINDOW or abusive toasts) on top of another application, so that the user's tap reaches the underlying app. It grants permissions, accepts dialogs or presses banking buttons without the person being aware of the hidden layer.
Double clickjacking (a modern bypass)
The double clickjacking technique, disclosed by Paulos Yibelo in late 2024, evades the classic defenses because it does not use an iframe. The attacker opens a popup window that asks for a double click (usually disguised as a captcha). Between the first and second click, on the mousedown event, the script redirects the parent window toward the real sensitive page (for example, an OAuth authorisation screen), so that the second click lands on the legitimate "Authorise" button. Since there is no framing, neither X-Frame-Options nor frame-ancestors intervene, and SameSite=Lax does not protect either because the navigation happens in the foreground. Mitigation requires disabling critical buttons until a verified user gesture is detected.
Real impact and classification
Clickjacking is rarely an end in itself: it is usually the trigger for higher impact actions. In real applications it has been used to force permission grants, activate microphone or camera, approve OAuth flows that hand full accounts to the attacker, confirm transfers or change email addresses (the antechamber of a password reset). Combined with an underlying CSRF, it supplies the human gesture that some defenses require.
In the weakness catalogue, it is identified as CWE-1021, and the historical mitigation header, X-Frame-Options, is standardised in RFC 7034. A search in the NVD for "clickjacking" returns recurring entries in admin panels, CMS plugins and enterprise consoles that ship without the framing header configured. The pattern is always the same: a sensitive action executable with one click and a page that lets itself be framed by third parties.
Defenses against clickjacking
X-Frame-Options
The response header X-Frame-Options: DENY forbids the page from being framed by any origin, and SAMEORIGIN allows it only from the same domain. It is the oldest defense and the one with the broadest coverage in legacy browsers. The ALLOW-FROM value is deprecated and should not be used because its support was always inconsistent.
CSP frame-ancestors
The modern directive is Content-Security-Policy: frame-ancestors. frame-ancestors 'none' is equivalent to DENY, frame-ancestors 'self' to SAMEORIGIN, and it accepts an allow list of specific origins (frame-ancestors 'self' https://trusted-partner.tld). Introduced in CSP level 2, it supersedes X-Frame-Options because it supports several authorised origins and is not limited to a single value. The professional recommendation is to send both headers to cover old and modern browsers, letting frame-ancestors prevail where it is supported.
SameSite cookies
SameSite=Lax (the default value in current browsers) or SameSite=Strict prevent the session cookie from travelling in cross site contexts, and content framed by an attacker is, by definition, cross site. This does not stop the page from being framed, but it degrades the impact: if the session does not accompany the iframe, the sensitive action is not authenticated. It is a valuable complementary defense, the same family of mitigations applied against CSRF.
Frame busting (legacy)
Frame busting through JavaScript (if (top !== self) top.location = self.location) was the handcrafted defense of the era before headers. Today it is considered insufficient on its own: the iframe sandbox attribute, onbeforeunload handling and other techniques allow it to be neutralised. It serves as an additional layer, never as the primary control.
User experience defenses
Irreversible actions should require an explicit confirmation that is hard to frame usefully, re authentication or a second factor. Disabling critical buttons until a legitimate user gesture is detected is, moreover, the specific mitigation against the double clickjacking described earlier.
How to test clickjacking in an audit
The initial diagnosis is direct: review the response headers with curl -I https://target.tld and check for the presence of X-Frame-Options and Content-Security-Policy: frame-ancestors. Services such as securityheaders.com offer a quick reading, although they never replace manual verification on the real sensitive routes.
Confirming exploitability is done with a real proof of concept. Burp Suite includes Clickbandit, which automatically generates an attack page framing the target and lets you validate whether a specific flow is hijackable. The process: identify the sensitive action endpoints (permissions, payments, account changes, OAuth authorisations), build a transparent iframe over each one, verify whether the browser renders it with the active session and test variants such as cursorjacking or double clickjacking on the critical flows. These checks are part of the usual scope of a web application penetration test aligned with the OWASP Web Security Testing Guide.
Frequently asked questions
Does clickjacking need to run JavaScript on the victim site?
No. Unlike XSS, clickjacking does not inject code into the target application. It only frames it from the outside. That is why a site with no injection flaw at all can still be vulnerable to clickjacking if it allows third party framing.
Is X-Frame-Options enough or do I need CSP frame-ancestors?
The robust approach is to send both. X-Frame-Options covers old browsers, and frame-ancestors is the modern directive with support for origin lists and finer control. Where both are present, modern browsers prioritise frame-ancestors.
Does SameSite on cookies stop clickjacking?
It does not prevent it, but it reduces its impact. SameSite=Lax or Strict stops the session cookie from accompanying cross site framed content, so the hijacked action is not authenticated. It is a layer complementary to the framing headers, not a substitute.
What is double clickjacking and why does it evade the classic defenses?
It is a technique that exploits the interval between the two clicks of a double click to switch the parent window to the sensitive page just before the second click. Since it uses no iframe, neither X-Frame-Options nor frame-ancestors intervene. It is mitigated by disabling critical buttons until a real user gesture is detected.
Related resources
- What is CSRF: cross-site request forgery, examples and defense
- What is XSS: cross-site scripting
- What is CORS and why it matters in web security
- OWASP Top 10 2025: business vulnerabilities
- Web and mobile security audit
Auditing clickjacking and UI redressing with Secra
Secra performs web application audits aligned with the OWASP Top 10 and the OWASP Web Security Testing Guide. We cover the review of X-Frame-Options and Content-Security-Policy: frame-ancestors headers, validation of the SameSite configuration of session cookies, and real proofs of concept for clickjacking, likejacking, cursorjacking and double clickjacking against your sensitive flows (permissions, payments, OAuth authorisations and account changes).
We deliver prioritised findings and hardening recommendations specific to your architecture, including regression suites that verify in CI that framing headers are not disabled when new routes are deployed. If you need a professional review of clickjacking and the rest of the OWASP catalogue, write to us through /en/contact.
About the author
Secra Solutions team
Ethical hackers with OSCP, OSEP, OSWE, CRTO, CRTL and CARTE certifications, 7+ years of experience in offensive cybersecurity, and authors of CVE-2025-40652 and CVE-2023-3512.

