Clickjacking
A complete guide to understanding, detecting, exploiting, and preventing Clickjacking vulnerabilities.
Introduction
Clickjacking (UI Redressing)
ANAS EDUCATION -- Bug Bounty & Pentesting Course (V2 Beginner-First)
SECTION 1. Introduction
Imagine you open your PC and visit `anastech.com`.
You log in. You navigate to `/my-account`. You see your profile. At the bottom of the page sits a big red button:
This button, when clicked, sends:
The server checks your session cookie. You are logged in. It checks the CSRF token in the form. The token is valid (it was generated by the same page). It deletes your account.
Normal. Expected. The user clicked their own button on their own browser tab.
Now look at the same picture again, but with a question on top of it: what if a different page, on a different domain, loaded `https://anastech.com/my-account` inside an invisible frame, and placed a visible button on top labeled "Click here for a free phone", positioned exactly where the real Delete Account button sits?
Browsers stack web pages in layers using a CSS property called `z-index`. The element with the higher `z-index` sits on top. When a user clicks, the browser sends the click to whichever element is at that pixel on top.
If the attacker's page sets:
- ●The decoy button: `z-index: 1`, visible, labeled "Free Phone".
- ●The hidden frame of anastech.com: `z-index: 2`, opacity `0.0001` (effectively invisible), positioned so the real Delete Account button sits at the exact same pixel coordinates as the decoy.
The user sees the decoy. The user clicks. The browser registers the click on the frame (which is on top). The frame is the real anastech.com page. The real Delete Account button receives the click. The user is logged in. The cookie is sent. The CSRF token is present in the framed form. The account is deleted.
The attacker did not break SQL, did not steal a session, did not bypass CSRF, did not break HTTPS, and did not phish a password. The attacker convinced a finger to land on a different button than the eye believed.
This is Clickjacking, also called UI redressing. It has been quietly draining accounts, hijacking OAuth approvals, stealing crypto, and deleting data for over fifteen years. It still works in 2026 against any page that omits one HTTP header.
This course teaches the Clickjacking bug class from zero. By the end you will know:
- ●Why browsers let cross-origin pages frame your site by default.
- ●Why CSRF tokens and SameSite cookies do not stop this attack.
- ●How to overlay an invisible iframe and align it with a real button.
- ●The five common variants: classic, prefilled-form, frame-buster-bypass, multistep, and clickjacking-to-XSS.
- ●How to detect, exploit, and prevent each variant with one HTTP header.
You do not need to be an expert in CSS. You need to understand that a click goes to the topmost element, and you control which element is on top.
SECTION 2. How It Works
To find these bugs you first need to understand how browsers render and route clicks.
Step 1. The browser layering engine
When an HTML document contains overlapping positioned elements, the browser computes a stacking order using the `z-index` CSS property. Higher values sit on top. The top element receives mouse events first.
If a user clicks at coordinates `(x, y)`, the browser performs a "hit test" and delivers the click to whichever element is on top at that pixel.
Step 2. The iframe
An `<iframe>` tag embeds one HTML document inside another. The framed document loads with its own session, its own cookies, its own JavaScript. From the parent's perspective the iframe is a single visual element it can position, size, and style with CSS, but it cannot read the framed content because of the browser's Same-Origin Policy.
If the user is logged in to anastech.com, that page loads inside the iframe with the user's cookies attached. The framed page is fully functional: clicks inside the iframe are real clicks on the real anastech.com page.
Step 3. Opacity
CSS `opacity` controls how transparent an element is. `opacity: 1` is fully opaque. `opacity: 0` is fully transparent. Critically, even at `opacity: 0`, clicks still register on the element. Only the visual is hidden.
This is the entire attack primitive: an invisible iframe that still receives clicks.
Step 4. The safe flow
There is no risk because anastech.com is not framed and not interacting with the user.
Step 5. The vulnerable flow
Step 6. Three conditions for the bug to exist
- ●1. The target page does not set `X-Frame-Options` or `Content-Security-Policy: frame-ancestors` to forbid framing.
- ●2. The user is authenticated to the target site (a session cookie exists in the browser).
- ●3. The target has a state-changing action reachable in one or two clicks.
All three are common. The first is the one the developer controls.
Step 7. Why CSRF tokens do not help
A CSRF token defends against requests forged by the attacker. In Clickjacking, the request is generated by the framed legitimate page. The token is generated by anastech.com inside the iframe, included automatically in the form, and submitted as part of the real click. The attacker never sees it and never needs it.
Step 8. Why SameSite cookies do not always help
`SameSite=Lax` and `SameSite=Strict` cookies are sent on first-party interactions. When the user is inside the framed anastech.com page, that page IS first-party relative to itself. The cookie is sent. SameSite blocks cross-site request forgery patterns, not Clickjacking.
`SameSite=Strict` does block cookies on iframes loaded from a different top-level site in modern browsers, which is why Strict provides incidental protection in some browser versions. But the canonical defense is frame-ancestors.
SECTION 3. Attack Flow
The walkthrough below shows a complete Clickjacking attack on a state-changing endpoint.
Step 1: Recon
Identify the target page that performs a sensitive action. Common candidates: delete account, change email, change password, disable 2FA, approve OAuth, transfer money, ban user (admin), delete content (admin).
Step 2: Frame test
Create a minimal HTML file:
Open it in a browser while logged in. If the page renders inside the iframe, framing is allowed and the target is potentially vulnerable.
Step 3: Inspect headers
Use browser DevTools (Network tab) to view the response headers for the target page. The presence of any of the following blocks framing:
- ●`X-Frame-Options: DENY`
- ●`X-Frame-Options: SAMEORIGIN`
- ●`Content-Security-Policy: frame-ancestors 'none'`
- ●`Content-Security-Policy: frame-ancestors 'self'`
If none are present, the target is framable.
Step 4: Measure the target button
Open the target page in DevTools. Right-click the sensitive button. Inspect. Read the bounding box coordinates: e.g., top: 515px, left: 70px on a 1000px-wide viewport.
Step 5: Build the proof of concept
Create an HTML file that loads the iframe with high `z-index` and low opacity, and a decoy button at low `z-index` positioned at the measured coordinates.
Step 6: Test with opacity 0.5
Set the iframe opacity to 0.5 first. Visually confirm the decoy aligns with the real button. Adjust coordinates until alignment is exact.
Step 7: Deploy with opacity 0.0001
Drop opacity to `0.0001`. The iframe is invisible but still receives clicks.
Step 8: Deliver
Host the page on attacker infrastructure. Deliver to the victim via phishing, social media link, malvertising, or any social engineering channel.
Step 9: Capture impact
When the victim clicks the decoy, the real action fires. Document with screenshots, network captures, and the resulting state change.
ASCII timing diagram
SECTION 4. Why Developers Make This Mistake
Clickjacking is not a code bug. It is a defaults bug.
Mistake 1: "My CSRF tokens protect me"
CSRF tokens defend against forged requests built by the attacker. Clickjacking uses the user's own click on the user's own browser inside the user's own session. The token is valid because the framed page generated it.
Mistake 2: "Nobody would put my site in an iframe"
Anyone with one HTML file and a hosting account can. Framing is a default-permitted browser behavior unless the page explicitly says otherwise.
Mistake 3: "SameSite cookies stop this"
SameSite cookies stop classic CSRF (forged requests in the background). They do not stop a click delivered to a framed page. In most browser versions, `SameSite=Lax` cookies are still sent inside an iframe.
Mistake 4: "Users will notice an invisible iframe"
By definition the iframe is invisible. The user sees only the decoy. There is no visual cue.
Mistake 5: "X-Frame-Options is legacy; I do not need it"
`X-Frame-Options` is legacy in name only. Modern browsers still honor it, and the modern replacement (`Content-Security-Policy: frame-ancestors`) is supported by every browser shipped in the last six years. One of the two should be present on every sensitive page.
Mistake 6: "JavaScript frame busters protect me"
A JavaScript snippet like `if (top != self) top.location = self.location;` is bypassable by `<iframe sandbox="allow-forms">` (scripts cannot execute), by `onbeforeunload` interception, and by several other documented tricks. HTTP headers cannot be bypassed by client-side CSS or sandbox tricks.
SECTION 5. Beginner Summary
- ●Clickjacking overlays the target site inside an invisible iframe on top of a visible decoy button on the attacker's page. The victim's click hits the iframe.
- ●The target page is loaded inside the victim's authenticated session, so any action the victim could perform legitimately can be triggered by the misdirected click.
- ●CSRF tokens, SameSite cookies, and most server-side defenses do not help because the request is generated by the legitimate page.
- ●The fix is one HTTP response header: `X-Frame-Options: DENY` or `Content-Security-Policy: frame-ancestors 'none'`. Set both for defense in depth.
- ●Detection is one HTML file: load the target inside an iframe; if it renders, the target is framable and the bug exists.
SECTION 6. Visual Explanation
The layering (what the user sees vs what the browser routes to)
Five families of Clickjacking
The defense stack
The attacker's CSS skeleton
SECTION 7. Definition
Technical definition
Clickjacking, also known as UI redressing or User Interface redress attack, is a vulnerability in which an attacker tricks a user into clicking a UI element of a target application that has been overlaid invisibly above a decoy on an attacker-controlled page. The browser delivers the click to the framed target, executing actions in the user's authenticated context without the user's awareness.
- ●CWE-1021: Improper Restriction of Rendered UI Layers or Frames
- ●OWASP A05:2021 Security Misconfiguration (missing frame-protection headers)
Beginner-friendly definition
Clickjacking is when an invisible copy of a real website sits on top of a fake button. The user sees the fake button, clicks it, and the click actually lands on the real button.
Why it matters
Clickjacking remains a live class of bug in 2026. Recent confirmation:
- ●Coinbase OAuth authorization page Clickjacking: HackerOne report https://hackerone.com/reports/65825, paid $5,000.
- ●WakaTime double-Clickjacking on the OAuth authorization flow (`https://wakatime.com/oauth/authorize`), 55 upvotes on HackerOne corpus.
- ●TikTok developer app deletion via Clickjacking, paid $500 (corpus reference).
- ●Shopify exchangemarketplace.com Clickjacking, disclosed report.
- ●Sifchain Clickjacking: https://hackerone.com/reports/1199904.
- ●Imgur self-XSS-to-account-takeover chained with Clickjacking in Firefox (corpus).
- ●Yelp business-page Clickjacking on multiple subdomains (corpus).
- ●Mail.ru "Make user buy items via Clickjacking" (corpus).
Even after fifteen years of documentation, sensitive pages still ship without `frame-ancestors`.
Common affected systems
- ●OAuth and SSO consent screens (high-value because of persistent third-party access)
- ●Account settings: change email, change password, disable 2FA
- ●Admin panels with destructive one-click actions (delete user, ban, refund)
- ●Cryptocurrency exchange withdrawal and 2FA pages
- ●Banking transfer confirmation pages
- ●Social media like, follow, share, send buttons
- ●API key management dashboards
- ●Subscription cancellation pages
- ●Healthcare consent pages and medical record release flows
If a page has a sensitive action one to two clicks away and no frame-ancestors policy, Clickjacking can hijack it.
SECTION 8. Examples
Each example uses the same template: the feature, the bug, the attack step by step.
Example 1. AnasMarket account deletion
The feature. AnasMarket's `/my-account` page has a "Delete Account" button that submits a POST with a CSRF token (generated on the page).
The bug. The page response does not include `X-Frame-Options` or `Content-Security-Policy: frame-ancestors`.
The attack step by step.
- ●Step 1: confirm framing works by loading the page inside an iframe in a local HTML file.
- ●Step 2: measure the Delete button position via DevTools.
- ●Step 3: build an attacker page with the iframe (z-index: 2, opacity: 0.0001) and a decoy "Click for prize" button at the measured coordinates (z-index: 1).
- ●Step 4: deliver the link.
- ●Step 5: the victim clicks; account is deleted.
Example 2. AnasOne email change via URL prefill
The feature. AnasOne supports `/account/update-email?email=<value>` as a URL parameter that prefills the email field on the update form.
The bug. No frame-ancestors, plus the URL parameter prefills sensitive data. The combination converts a meaningless click into an account-takeover trigger.
The attack step by step.
- ●Step 1: build a page that frames `https://anasone.anastech.com/account/update-email?email=attacker@evil.com`.
- ●Step 2: align the decoy over the "Save" button.
- ●Step 3: victim clicks; email becomes `attacker@evil.com`.
- ●Step 4: attacker triggers password reset to that email and takes over the account.
Example 3. AnasDocs frame-buster bypass
The feature. AnasDocs has a JavaScript frame buster on its admin pages:
The bug. The page lacks frame-ancestors, relying entirely on the JS buster.
The attack step by step.
- ●Step 1: load the iframe with `sandbox="allow-forms"`. The sandbox attribute disables scripts; the buster cannot run.
- ●Step 2: the iframe stays loaded.
- ●Step 3: align a decoy over a sensitive button.
- ●Step 4: victim clicks; action executes.
Sandbox bypass is the canonical PortSwigger lab 3 pattern.
Example 4. AnasSocial Clickjacking-to-DOM-XSS chain
The feature. AnasSocial has a `/feedback?name=...&email=...&message=...` endpoint that reads URL parameters via JavaScript and writes them into the DOM unsafely (a DOM-XSS that requires the user to visit the URL).
The bug. The form is also framable with no frame-ancestors. Standalone DOM-XSS requires the user to visit a malicious URL; with Clickjacking the user "submits" the form themselves by clicking the framed Submit button.
The attack step by step.
- ●Step 1: frame `/feedback?name=<img src=1 onerror=alert(document.cookie)>&...#feedbackResult`.
- ●Step 2: align decoy over the framed Submit button.
- ●Step 3: victim clicks; the form submits; the DOM payload renders; the XSS executes inside anassocial.com session context.
Example 5. AnasCorp multistep admin deletion
The feature. AnasCorp's admin "Delete Car" flow requires two clicks: one on the Delete button and one on the Confirm button in a modal that appears.
The bug. No frame-ancestors; both buttons in fixed positions.
The attack step by step.
- ●Step 1: build an attacker page with two sequential decoys ("Click 1 of 2 for prize" and "Click 2 of 2 for prize").
- ●Step 2: position decoy 1 over the Delete button and decoy 2 over the Confirm button.
- ●Step 3: victim clicks both in sequence; car is deleted.
PortSwigger lab 5 follows this exact pattern.
SECTION 9. Vulnerable Code
Configuration failure: response with no frame headers
The vulnerability is the absence of headers, not the presence of malicious code.
PHP
The CSRF token is present but does not block Clickjacking. The page is framable.
Node.js (Express)
Without `helmet` (or equivalent), Express ships no frame-protection headers.
Python (Flask)
Python (Django)
`xframe_options_exempt` is intended for embeddable widgets only; using it on a sensitive page is the modern shape of the bug.
Java (Spring Security)
Sometimes disabled to support a legitimate iframe widget, then left disabled application-wide.
.NET (ASP.NET)
Weak defense: JavaScript frame buster only
Bypasses:
- ●`<iframe sandbox="allow-forms">` ==> scripts cannot run; buster never fires
- ●`<iframe sandbox="allow-scripts">` ==> scripts run but `top.location` write is blocked
- ●Parent `onbeforeunload` handler ==> intercepts navigation
- ●Double framing (frame inside frame inside frame) ==> some implementations only check direct parent
- ●Slow loading: the buster races with the click
Frame busters belong as a third layer, never as the only defense.
The universal pattern across languages
- ●1. The application returns HTML that needs to be protected from being embedded.
- ●2. The response does not contain `X-Frame-Options` or `Content-Security-Policy: frame-ancestors`.
- ●3. Sometimes a JS frame buster is present but bypassable.
- ●4. Any cross-origin page can frame the response.
Step 2 is the bug. Every fix sets one of those two headers.
EOFSECTION_NEVER_USED
SECTION 10. Detection
Clickjacking detection has two phases. Phase one confirms the page can be framed. Phase two confirms a meaningful action can be hijacked.
Manual workflow
- ●Step 1: log in to the target site.
- ●Step 2: open DevTools, Network tab, reload the sensitive page.
- ●Step 3: inspect the response headers of the main HTML response. Look for `X-Frame-Options` and `Content-Security-Policy` with `frame-ancestors`. If both are absent or both are permissive, framing is allowed.
- ●Step 4: create a minimal HTML file with `<iframe src="TARGET_URL"></iframe>` and open it locally. If the page renders, framing works.
- ●Step 5: identify the sensitive button or link. Common targets: delete account, change email/password, disable 2FA, transfer money, approve OAuth, admin destructive actions.
- ●Step 6: measure pixel coordinates using DevTools (right-click target button, Inspect, read bounding box).
- ●Step 7: build the PoC with iframe `z-index: 2` and `opacity: 0.0001`, decoy at `z-index: 1` positioned at the measured coordinates.
- ●Step 8: test with `opacity: 0.5` first to verify alignment, then drop to `0.0001`.
Burp Suite
- ●Right-click any request in Proxy/Repeater and select "Engagement tools" -> "Generate CSRF PoC" (works for Clickjacking too in many Burp versions; otherwise use Clickbandit).
- ●Use the Burp Clickbandit extension for interactive PoC generation.
- ●Active Scan flags missing `X-Frame-Options` and weak `frame-ancestors` automatically.
Automated tools and URLs
- ●PortSwigger Clickbandit -- interactive PoC generator: https://portswigger.net/clickbandit
- ●OWASP ZAP passive scan -- flags missing frame headers
- ●Mozilla Observatory -- header audit including frame protection: https://observatory.mozilla.org/
- ●SecurityHeaders.com -- quick scan: https://securityheaders.com/
- ●Nuclei templates -- missing security headers: https://github.com/projectdiscovery/nuclei-templates
Quick command-line probe
If the output is empty, the page has no frame protection.
Indicators of vulnerability
- ●Response missing both `X-Frame-Options` and `Content-Security-Policy: frame-ancestors`.
- ●JS frame buster as the only defense.
- ●Sensitive state-changing action reachable in one click from a page that lacks headers.
- ●URL parameters that prefill form fields, converting a meaningless click into a meaningful state change.
- ●Confirmation modals with predictable, fixed positions.
- ●OAuth consent screens without frame headers (high-value target).
- ●Admin panels not behind a dedicated security-headers middleware.
SECTION 11. Exploitation
Exploitation goes from a one-liner PoC to multistep chains with prefilled state and XSS triggers.
Workflow
- ●1. Confirm framing works.
- ●2. Identify a sensitive button at known coordinates.
- ●3. Build the iframe + decoy PoC.
- ●4. Verify alignment at opacity 0.5.
- ●5. Set opacity 0.0001 and host the PoC.
- ●6. Deliver via phishing or social engineering.
- ●7. Capture impact (account deleted, email changed, 2FA disabled).
Techniques
1. Classic iframe overlay
2. Iframe with prefilled URL parameters
When the target accepts URL parameters that prefill form fields:
The iframe loads with the attacker-controlled value already in the form. The framed Save button accepts it as if the user typed it.
3. Sandbox attribute to defeat JS frame busters
`allow-forms` permits form submissions but blocks scripts entirely. The frame buster (a script) cannot run. The iframe stays loaded.
Alternative:
Scripts run but `top.location` writes require `allow-top-navigation`, which is not in the sandbox list, so the buster's navigation is blocked.
4. Multistep (multistage) Clickjacking
Two or more decoys positioned over consecutive buttons in a workflow (e.g., Delete -> Confirm):
5. Clickjacking-to-DOM-XSS
The framed page reads the URL parameter `name` into the DOM unsafely. The victim's click submits the form, the page reloads, and the payload executes inside target context.
6. Drag-and-drop hijacking
Some attacks use CSS to misdirect drags. The user drags a slider thinking they are positioning a UI control, but the framed page captures the drag and applies it to a different element. Historical example: Adobe Flash settings page where users dragged a permission slider to "Allow" without realizing.
7. Cursor spoofing
A custom cursor with an offset displaces the visible pointer from the actual click pixel. The user aims at the visible cursor; the click lands where the real pointer (offset) actually is.
8. Keystroke hijacking
Focus an invisible input from the framed page via JavaScript; prompt the user to type something on the decoy. The keystrokes land in the iframe's form. Combined with auto-submit, the form fires when filled.
9. File-input hijacking
When the target has a file picker, align the decoy "Choose theme" over the framed file input. The user clicks; the framed file picker opens. Limited but real impact in specific flows.
10. Window-position attack
Resize the attacker window to expose only the click area of the iframe. The visible portion is the decoy. The rest is offscreen.
11. Pop-under variant
Open the target in a popup window positioned partially behind the visible attacker page. CSS and timing misdirect clicks to the partially-hidden popup. Modern popup blockers limit this; still surfaces occasionally.
12. OAuth consent Clickjacking
OAuth authorization screens are high-value targets: a single click can grant a third-party application persistent access to the victim's account. The Coinbase finding at https://hackerone.com/reports/65825 paid $5,000 for exactly this pattern.
13. Double-Clickjacking on OAuth
The WakaTime OAuth flow disclosure on HackerOne is the canonical example. The user clicks one decoy; the OAuth screen advances; the user clicks the second decoy; the OAuth grant is approved.
14. Reflected-content Clickjacking
If the framed page reflects a URL parameter into a button label, an attacker can frame `target/search?q=Confirm+delete` so the visible iframe (when partially opaque for the attack) reads naturally and even sophisticated users may not notice.
15. Iframe of iframe (nested framing)
Some bypasses chain: attacker page frames a permissive third-party site that itself frames the target. Useful when the target uses `X-Frame-Options: SAMEORIGIN` and the third-party page is on the same origin.
16. SVG/HTML data URI decoy
Used to inline-load attacker HTML in environments that block external resources. Niche.
17. Mobile webview Clickjacking
In hybrid mobile apps with embedded webviews, the underlying app sometimes ships without frame-protection headers. The attacker presents a fake banner overlay inside the same webview; the user taps; the framed action fires.
18. SSO/SAML Clickjacking
SSO pages without `frame-ancestors` can be framed; users tricked into authorizing a SAML assertion grant the attacker federated access.
19. Combined with phishing
The decoy is part of a phishing page that looks like a legitimate brand. The victim trusts the page; the click fires the framed action with the victim's existing session on the real target.
20. Like-jacking and share-jacking
The original mass attacks: decoy looks like a video or game; the framed Like button on a social platform receives the click; the victim's feed shows a like that they did not perform.
SECTION 12. Proof of Concept
Burp Suite
- ●1. Capture the response of the sensitive page.
- ●2. Confirm absence of frame-protection headers.
- ●3. Right-click and select "Generate Clickjacking PoC" (Burp Pro) or use Clickbandit BApp.
- ●4. Burp generates an HTML file with iframe + decoy.
- ●5. Adjust coordinates; test at opacity 0.5; finalize at opacity 0.0001.
PortSwigger Clickbandit
- ●1. Visit https://portswigger.net/clickbandit.
- ●2. Drag the bookmarklet to your bookmarks bar (or paste in DevTools console).
- ●3. Navigate to the target while logged in.
- ●4. Activate Clickbandit; click through the action you want to hijack.
- ●5. Clickbandit records and generates a working PoC HTML.
Canonical PoC (PortSwigger lab style)
Frame-buster bypass via sandbox
Clickjacking-to-DOM-XSS PoC
Multistep PoC
Production-quality decoy
Python header scanner PoC
Bash one-liner
SECTION 13. Payloads
Clickjacking "payloads" are HTML/CSS positioning skeletons plus iframe attributes.
Tier 1: minimal proof
If it renders, framing is possible.
Tier 2: classic overlay
Tier 3: URL-prefilled exploitation
Tier 4: sandbox bypass
Tier 5: multistep
Tier 6: chained DOM-XSS
Tier 7: cursor spoof
Tier 8: window-positioned stealth
Tier 9: nested iframe (X-Frame-Options: SAMEORIGIN bypass when a same-origin page is permissive)
Tier 10: data: URI decoy (offline)
SECTION 14. Wordlists and Payload Libraries
- ●PortSwigger Clickbandit -- interactive PoC generator: https://portswigger.net/clickbandit
- ●PortSwigger Web Security Academy -- Clickjacking labs: https://portswigger.net/web-security/clickjacking
- ●PayloadsAllTheThings -- Clickjacking: https://github.com/swisskyrepo/PayloadsAllTheThings (search "clickjacking")
- ●HackTricks -- Clickjacking: https://book.hacktricks.xyz/pentesting-web/clickjacking
- ●OWASP Clickjacking Defense Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html
- ●OWASP Testing Guide -- Testing for Clickjacking: https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/11-Client-side_Testing/09-Testing_for_Clickjacking
- ●MDN -- X-Frame-Options: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
- ●MDN -- CSP frame-ancestors: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors
- ●Mozilla Observatory -- security headers audit: https://observatory.mozilla.org/
- ●SecurityHeaders.com -- header scan: https://securityheaders.com/
- ●reddelexc Top Clickjacking corpus: https://github.com/reddelexc/hackerone-reports/blob/master/tops_by_bug_type/TOPCLICKJACKING.md
- ●Anas Magane Pentesting Notes -- Clickjacking: https://github.com/Anas-Magane/Pentesting/tree/main/TOP_10_OWASP
Practical advice
- ●Keep a 5-line PoC template ready: iframe with `z-index: 2 opacity: 0.0001`, decoy div with `z-index: 1`, two CSS coordinates, one iframe URL.
- ●Maintain a small set of polished decoys ("Free Phone", "Newsletter Unsubscribe", "Watch the Match Live") -- the social-engineering polish drives click-through.
- ●Build a one-line scanner with `curl -I` for missing headers to triage targets quickly.
- ●Save real bounty PoCs from disclosed HackerOne reports as a reference library.
SECTION 15. Impact
Impact ranges from low (likejacking) to critical (admin destructive actions or OAuth account takeover).
Step 1: information disclosure
The decoy alignment exposes the visual structure of a page that may be behind authentication, indicating internal layouts or feature presence.
Step 2: nuisance UI actions
Force a victim to like, follow, share, or favorite. Low impact unless combined with other vectors.
Step 3: profile modification
Change preferences, notification settings, or non-critical fields.
Step 4: email change
Combined with URL prefill, email change is the gateway to account takeover via password reset.
Step 5: 2FA disablement
Decoy over the "Disable 2FA" button; victim's account is now weaker for further attacks.
Step 6: OAuth approval / SSO grant
Single click grants persistent third-party access. The Coinbase HackerOne report at https://hackerone.com/reports/65825 paid $5,000 for this. WakaTime double-Clickjacking on the OAuth flow is a higher-tier variant.
Step 7: payment / transfer
Where allowed by application design, a misdirected click transfers funds or makes purchases.
Step 8: account deletion
One click, account gone. Hard to undo on most platforms.
Step 9: admin actions
On admin panels: delete user, ban, refund, modify roles, grant access. Compound impact across the user base.
Step 10: account takeover via chain
Clickjacking + email change + password reset = full ATO without credential theft.
Step 11: persistent third-party access
OAuth grant to attacker app survives password rotation; the attacker reads inbox/data persistently.
Step 12: phishing amplification
Clickjacking inside a believable phishing page massively increases conversion from impression to compromise.
Step 13: regulatory and contractual fallout
GDPR, HIPAA, PCI DSS violations when sensitive actions execute without user consent.
Step 14: reputational damage
Public disclosure of OAuth or admin Clickjacking on banking or crypto platforms shrinks user trust.
Step 15: long-tail cost
Remediation, audit cycles, deployment of header policies across legacy services.
SECTION 16. Prevention
The fix is one HTTP response header per page. Defense-in-depth combines two headers plus cookie attributes and re-authentication on sensitive actions.
The two rules that cover almost everything
- ●1. Every authenticated and state-changing page sets `Content-Security-Policy: frame-ancestors 'none'` (or a strict allowlist).
- ●2. The same pages also set `X-Frame-Options: DENY` as legacy fallback.
If both hold, classical Clickjacking cannot happen.
Header values explained
`Content-Security-Policy: frame-ancestors` is the modern preferred header. `X-Frame-Options` is the legacy fallback for older browsers. Set both for compatibility.
Vulnerable vs safe (Node.js Express with Helmet)
Vulnerable:
Safe:
Vulnerable vs safe (Python Django)
Django 2.0+ ships X-Frame-Options middleware by default. Keep it enabled:
Avoid `@xframe_options_exempt` on sensitive views.
Vulnerable vs safe (Python Flask)
Vulnerable vs safe (Java Spring Security)
Spring Security adds `X-Frame-Options: DENY` by default. Add CSP frame-ancestors:
Vulnerable vs safe (.NET ASP.NET Core)
Vulnerable vs safe (PHP)
Apply via a central include or a security-headers middleware (e.g., `paragonie/csp-builder`).
Vulnerable vs safe (NGINX)
Vulnerable vs safe (Apache)
Additional layered defenses
- ●Session cookie attributes: `SameSite=Strict; Secure; HttpOnly`. Strict provides incidental protection in modern browsers.
- ●Sensitive actions: require password re-authentication or step-up MFA. Even a misdirected click cannot complete the action without the password.
- ●Avoid GET for state changes. State changes go through POST or PUT.
- ●Confirmation modals that cannot be aligned together as a fixed multi-click sequence (e.g., randomized button positions on confirm).
- ●Server-side: log and alert on `frame-ancestors` CSP violation reports (`report-uri`/`report-to`).
Developer checklist
- ●Every authenticated page has both `X-Frame-Options` and `Content-Security-Policy: frame-ancestors` set.
- ●Headers come from central middleware, not per-controller.
- ●No `xframe_options_exempt`, no `frameOptions().disable()`, no per-page exceptions on sensitive pages.
- ●OAuth/SSO consent screens are explicitly listed for review.
- ●Admin panel pages are pinned to `frame-ancestors 'none'`.
- ●No JavaScript frame buster is treated as the sole defense.
- ●Sensitive actions require re-authentication or step-up MFA.
- ●CI test asserts the presence of the headers on every protected route.
- ●Mozilla Observatory / SecurityHeaders.com checked at deploy time.
Enterprise mitigations
- ●CDN/edge enforcement of frame-protection headers (Cloudflare, Akamai, Fastly transforms).
- ●WAF rule that injects `X-Frame-Options: DENY` if missing (last-resort safety net).
- ●SAST rule: flag `frameOptions().disable()`, `@xframe_options_exempt`, missing `helmet` in Node.
- ●Browser-side reporting via `CSP report-uri` collects framing attempts in the wild.
- ●Bug bounty programs scoped to include Clickjacking explicitly.
Why JavaScript frame busters are not enough
Bypasses:
- ●`<iframe sandbox="allow-forms">` blocks scripts entirely
- ●`<iframe sandbox="allow-scripts">` blocks `top.location` writes
- ●`onbeforeunload` in the parent intercepts navigation
- ●Double framing (nested iframes) confuses naive direct-parent checks
- ●Slow loading races where the click happens before the buster runs
Use HTTP headers, not JavaScript, as the primary defense.
SECTION 17. Real-World Cases
Historical landmarks
- ●Adobe Flash settings webcam Clickjacking (2008): Jeremiah Grossman and Robert Hansen named the attack class while demonstrating webcam/microphone permission hijack via UI redress on the Flash settings page.
- ●Twitter "Don't Click" worm (2009): viral Clickjacking that hijacked Twitter follow buttons; led Twitter to deploy frame protection across the platform.
- ●Facebook likejacking era (2010-2014): hundreds of campaigns hijacked Facebook Like buttons. Facebook hardened framing on all interactive elements.
Recent real HackerOne bug bounty reports
- ●Coinbase -- OAuth authorization page vulnerable to Clickjacking (paid $5,000)
Report: https://hackerone.com/reports/65825 Fix: ensured OAuth responses included the same security headers (including X-Frame-Options) as the rest of the site. Lesson: OAuth screens are high-value Clickjacking targets; single grant = persistent third-party access.
- ●WakaTime -- Double Clickjacking on OAuth authorization flow at https://wakatime.com/oauth/authorize
HackerOne corpus entry, 55 upvotes. Lesson: multistep Clickjacking on OAuth (two aligned clicks) defeats single-confirmation defenses.
- ●WakaTime -- Clickjacking on https://wakatime.com/share/embed (authorized page).
Lesson: even "share" or "embed" pages need protection if they include any state-changing or trust-elevating action.
- ●Sifchain -- Clickjacking on multiple URLs
Report: https://hackerone.com/reports/1199904 Lesson: many subdomains and routes; one missing header policy across them all.
- ●Shopify -- Clickjacking on exchangemarketplace.com
HackerOne corpus entry. Lesson: secondary marketplaces and integrations often lag the main brand on header hygiene.
- ●Nord Security (NordVPN) -- Clickjacking at join.nordvpn.com
HackerOne corpus entry. Lesson: marketing/signup pages also matter when they wrap account creation or upgrade.
- ●WordPress -- Clickjacking in jobs.wordpress.net and wordcamp.org
HackerOne corpus entries. Lesson: large multi-property orgs miss headers on owned but lower-traffic properties.
- ●TikTok -- Clickjacking can delete developer app (paid $500)
HackerOne corpus entry. Lesson: developer dashboards are sensitive even when not consumer-facing.
- ●TikTok -- Clickjacking & CSRF chain on TikTok Ads Portal
HackerOne corpus entry; CSRF $1,000. Lesson: ad and merchant portals are particularly impactful targets.
- ●X (Twitter) / xAI -- "Viral Direct Message Clickjacking via link truncation" leading to capture of Google credentials & installation of malicious third-party Twitter app (64 upvotes).
Lesson: chaining Clickjacking with content manipulation (link truncation) creates compound attacks.
- ●X (Twitter) / xAI -- Stealing user emails by Clickjacking cards.twitter.com
HackerOne corpus entry. Lesson: PII can leak through Clickjacking on auxiliary surfaces.
- ●Automattic / Tumblr -- Exploiting Clickjacking vulnerability to trigger self DOM-based XSS on api.tumblr.com
HackerOne corpus entry. Lesson: Clickjacking-to-XSS chains turn "low" findings into high-severity executions.
- ●Mail.ru -- Modifying application settings via Clickjacking on o2.mail.ru (paid $150).
Report listing in https://github.com/reddelexc/hackerone-reports/blob/master/tops_by_bug_type/TOPCLICKJACKING.md Lesson: even small settings changes can cascade.
- ●Mail.ru -- "Make user buy items via Clickjacking possibility"
HackerOne corpus entry. Lesson: e-commerce purchase flows without frame protection are direct financial impact.
- ●Imgur -- Self-XSS + Clickjacking leads to account takeover in Firefox
HackerOne corpus entry. Lesson: combine Clickjacking with self-XSS to overcome the "user must paste payload" limitation.
- ●U.S. Dept of Defense -- Reflected XSS through Clickjacking
HackerOne corpus entries (multiple). Lesson: government VDP programs accept and triage Clickjacking-chained findings.
- ●Yahoo (Flickr) -- Bypass of Clickjacking protection on Flickr using data URL in iframes
HackerOne corpus entry. Lesson: defenses that allow `data:` URI iframes can be circumvented.
Curated corpora
- ●Top Clickjacking reports: https://github.com/reddelexc/hackerone-reports/blob/master/tops_by_bug_type/TOPCLICKJACKING.md
- ●HackerOne Hacktivity (Clickjacking filter): https://hackerone.com/hacktivity?queryString=clickjacking
Lessons learned
- ●Clickjacking is alive in 2026 on every category of site.
- ●OAuth consent screens are the highest-paying Clickjacking targets.
- ●Multistep variants beat single-confirmation defenses.
- ●Combined with prefilled URL params, "one meaningless click" becomes account takeover.
- ●The fix is one HTTP header; the cost of forgetting it is the price of any disclosed report above.
SECTION 18. References
Standards and frameworks
- ●OWASP Clickjacking: https://owasp.org/www-community/attacks/Clickjacking
- ●OWASP Clickjacking Defense Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html
- ●OWASP Testing Guide -- Testing for Clickjacking: https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/11-Client-side_Testing/09-Testing_for_Clickjacking
- ●CWE-1021: Improper Restriction of Rendered UI Layers or Frames: https://cwe.mitre.org/data/definitions/1021.html
- ●OWASP Top 10 (Clickjacking mapped to A05:2021 Security Misconfiguration): https://owasp.org/Top10/
Browser documentation
- ●MDN X-Frame-Options: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
- ●MDN CSP frame-ancestors: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors
- ●MDN iframe sandbox attribute: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#sandbox
- ●MDN SameSite cookies: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value
Learning resources
- ●PortSwigger Clickjacking Academy: https://portswigger.net/web-security/clickjacking
- ●PortSwigger Clickbandit: https://portswigger.net/clickbandit
- ●HackTricks Clickjacking: https://book.hacktricks.xyz/pentesting-web/clickjacking
- ●PayloadsAllTheThings (Clickjacking section): https://github.com/swisskyrepo/PayloadsAllTheThings
Tools
- ●Burp Suite (PoC generation): https://portswigger.net/burp
- ●OWASP ZAP (passive scan for header presence): https://www.zaproxy.org/
- ●Mozilla Observatory: https://observatory.mozilla.org/
- ●SecurityHeaders.com: https://securityheaders.com/
Curated corpora
- ●reddelexc Top Clickjacking reports: https://github.com/reddelexc/hackerone-reports/blob/master/tops_by_bug_type/TOPCLICKJACKING.md
- ●HackerOne Hacktivity: https://hackerone.com/hacktivity?queryString=clickjacking
CVE/advisory feeds (Clickjacking is often advisory-only since the fix is server config)
- ●NVD: https://nvd.nist.gov
- ●GitHub Advisories: https://github.com/advisories
- ●Anas Magane Pentesting Notes: https://github.com/Anas-Magane/Pentesting
SECTION 19. Practical Labs
Planned ANAS Clickjacking Labs (SOON)
- ●ANAS-CJ-01 -- AnasMarket Classic Account Deletion, beginner
- ●ANAS-CJ-02 -- AnasOne URL-prefilled Email Change, beginner
- ●ANAS-CJ-03 -- AnasDocs Frame-Buster Bypass with sandbox, intermediate
- ●ANAS-CJ-04 -- AnasSocial Clickjacking-to-DOM-XSS, intermediate
- ●ANAS-CJ-05 -- AnasCorp Multistep Admin Confirmation, intermediate
- ●ANAS-CJ-06 -- AnasOne OAuth Consent Clickjacking, advanced
- ●ANAS-CJ-07 -- AnasBank 2FA Disable, advanced
- ●ANAS-CJ-08 -- AnasMarket Cursor Spoofing, advanced
- ●ANAS-CJ-09 -- AnasTravel Drag-and-Drop Hijack, advanced
- ●ANAS-CJ-10 -- AnasMarket SAMEORIGIN bypass via nested iframe, advanced
- ●ANAS-CJ-11 -- AnasOne data:URI bypass of weak defense, advanced
- ●ANAS-CJ-12 -- AnasCorp Admin Panel Compound Chain (Clickjacking + CSRF gap), expert
PortSwigger Web Security Academy Clickjacking labs
- ●Basic Clickjacking with CSRF token protection (APPRENTICE): https://portswigger.net/web-security/clickjacking/lab-basic-csrf-protected
- ●Clickjacking with form input data prefilled from a URL parameter (APPRENTICE): https://portswigger.net/web-security/clickjacking/lab-prefilled-form-input
- ●Clickjacking with a frame buster script (PRACTITIONER): https://portswigger.net/web-security/clickjacking/lab-frame-buster-script
- ●Exploiting Clickjacking vulnerability to trigger DOM-based XSS (PRACTITIONER): https://portswigger.net/web-security/clickjacking/lab-exploiting-to-trigger-dom-xss
- ●Multistep Clickjacking (PRACTITIONER): https://portswigger.net/web-security/clickjacking/lab-multistep
Self-hosted lab targets
- ●bWAPP -- Clickjacking lesson: http://www.itsecgames.com
- ●DVWA -- some Clickjacking variants: https://github.com/digininja/DVWA
- ●WebGoat (OWASP) -- UI redress lesson: https://github.com/WebGoat/WebGoat
Lab progression suggestion
- ●Week 1: PortSwigger Apprentice labs + ANAS-CJ-01/02 + sections 1-8 of this course.
- ●Week 2: PortSwigger Practitioner labs + ANAS-CJ-03/04/05 + read every disclosed bounty report in section 17.
- ●Week 3: ANAS-CJ-06/07/08 + try Clickbandit on a private app you own.
- ●Week 4: ANAS-CJ-09 to 12 + start hunting on programs that explicitly scope Clickjacking.
SECTION 20. Cheat Sheet
SECTION 21. Exam
Thirty multiple-choice questions. Answer key at the end.
- ●1. The core CSS property that controls which element receives a click in a stacked layout is:
A) display B) opacity C) z-index D) visibility
- ●2. Which `opacity` value keeps an iframe invisible but still clickable?
A) display:none B) visibility:hidden C) opacity:0.0001 D) width:0
- ●3. The fundamental difference between Clickjacking and CSRF:
A) Same attack, different name B) CSRF requires a user click; Clickjacking does not C) Clickjacking requires a user click; CSRF does not D) Only CSRF uses cookies
- ●4. The CWE most directly mapped to Clickjacking is:
A) CWE-79 B) CWE-352 C) CWE-1021 D) CWE-89
- ●5. The OWASP Top 10 (2021) category that covers Clickjacking is:
A) A01 Broken Access Control B) A03 Injection C) A05 Security Misconfiguration D) A09 Security Logging Failures
- ●6. The modern preferred header to forbid framing is:
A) X-Content-Type-Options B) Strict-Transport-Security C) Content-Security-Policy: frame-ancestors D) Referrer-Policy
- ●7. `X-Frame-Options: DENY` means:
A) No site can frame the page (including same origin) B) Only same origin can frame C) Any site can frame D) Only `*` can frame
- ●8. The decoy in a Clickjacking PoC is positioned with:
A) z-index higher than the iframe B) z-index lower than the iframe C) Same z-index as iframe D) No z-index
- ●9. CSRF tokens defend against Clickjacking?
A) Yes, always B) No, because the request is generated by the framed legitimate page C) Only if rotated frequently D) Only with HTTPS
- ●10. A JS frame buster `if (top != self) top.location = self.location` can be bypassed by:
A) `<iframe sandbox="allow-forms">` -- scripts cannot run B) Compressing the page C) Removing the script tag client-side D) Disabling HTTPS
- ●11. To convert a meaningless click into an account-takeover trigger:
A) Use a URL parameter that prefills sensitive form fields B) Use SQLi C) Use SSRF D) Use cookies
- ●12. A multistep Clickjacking PoC:
A) Uses a single decoy B) Uses two or more decoys positioned over consecutive buttons in a flow C) Requires SQL injection D) Requires a frame buster
- ●13. The Coinbase OAuth Clickjacking bounty paid:
A) $50 B) $500 C) $5,000 D) $50,000
- ●14. The 2008 Adobe Flash Clickjacking research targeted:
A) Webcam/microphone permission prompts via UI redress B) The Flash uninstaller C) The Flash debugger D) The Flash IDE
- ●15. Clickjacking-to-DOM-XSS works by:
A) Framing the page with a URL param that contains the XSS payload, then aligning a decoy over the form's Submit button B) SQLi C) Stealing cookies D) DNS rebinding
- ●16. The sandbox attribute `allow-forms`:
A) Disables scripts in the iframe (defeating frame busters) while still allowing form submission B) Allows scripts C) Allows top navigation D) Removes the iframe
- ●17. A page returns `Content-Security-Policy: frame-ancestors 'self'`. This means:
A) Any origin can frame B) Only same origin can frame C) No site can frame D) The page is broken
- ●18. Best opacity value when testing PoC alignment:
A) 0 B) 0.0001 C) 0.5 D) 1.0
- ●19. Which is the highest-impact Clickjacking target?
A) Static About Us page B) OAuth consent screen C) Privacy Policy page D) Sitemap
- ●20. Helmet's `frameguard({ action: 'deny' })` in Node Express:
A) Sets `X-Frame-Options: DENY` B) Removes cookies C) Enables CORS D) Disables HTTPS
- ●21. Django's default frame protection is set by:
A) `XFrameOptionsMiddleware` to `X-Frame-Options: SAMEORIGIN` B) HTTPS C) `MIDDLEWARE = []` D) Django does not protect against framing
- ●22. Spring Security's default `frameOptions()` setting is:
A) ALLOW B) DENY (i.e., `X-Frame-Options: DENY` is enabled by default) C) SAMEORIGIN D) None
- ●23. The Clickbandit tool by PortSwigger is:
A) A WAF B) An interactive PoC generator for Clickjacking C) An XML parser D) A JWT cracker
- ●24. Which is NOT a typical Clickjacking impact?
A) Account deletion B) OAuth grant C) SQL data exfiltration D) 2FA disable
- ●25. The CSP directive that controls who can frame a page is:
A) script-src B) frame-src C) frame-ancestors D) form-action
- ●26. To detect Clickjackability with one shell command:
A) `nslookup target` B) `curl -sI URL | grep -i 'x-frame\|frame-ancestors'` C) `traceroute target` D) `ping target`
- ●27. Cursor spoofing in Clickjacking is:
A) Hiding the click handler B) Displacing the visible pointer from the actual click pixel via custom cursor offset C) Disabling mouse input D) Showing a different cursor color
- ●28. Mobile webview Clickjacking is possible when:
A) The underlying page lacks frame-ancestors and is loaded inside a webview that allows another HTML overlay B) Bluetooth is enabled C) Wi-Fi is disabled D) GPS is on
- ●29. Which combination produces a real account takeover via Clickjacking?
A) Frame the email-change form with `?email=attacker@evil.com` prefilled, victim clicks framed Save, then attacker triggers password reset to the new email B) Steal the password via WebSocket C) Disable HTTPS D) Brute-force the password
- ●30. The single most important takeaway about Clickjacking:
A) CSRF tokens cover all UI attacks B) SameSite cookies cover all UI attacks C) The fix is one HTTP header; the cost of forgetting it puts users one click from compromise D) Modern browsers prevent Clickjacking automatically by default
Answer key
- ●1.C 2.C 3.C 4.C 5.C 6.C 7.A 8.B 9.B 10.A
- ●11.A 12.B 13.C 14.A 15.A 16.A 17.B 18.C 19.B 20.A
- ●21.A 22.B 23.B 24.C 25.C 26.B 27.B 28.A 29.A 30.C
Scoring
- ●27 to 30: Clickjacking expert.
- ●24 to 26: Solid.
- ●19 to 23: Functional; re-read sections 11 and 16.
- ●Below 19: re-read sections 1 to 8 and retake.
SECTION 22. Certificate Requirements
- ●Read all 24 sections of this course.
- ●Score 24/30 or higher on section 21.
- ●Complete all 5 PortSwigger Web Security Academy Clickjacking labs.
- ●Complete at least 8 of the 12 planned ANAS Clickjacking Labs (once released).
- ●Build a working PoC against a controlled target that demonstrates a real state change (not just "page is framable").
- ●Document one Clickjacking finding end-to-end in a write-up of 500+ words, with screenshots, HTTP traces, and the exact fix.
- ●Maintain a personal payload library of 15+ Clickjacking templates organized by tier.
Ethical baseline
The techniques here work against live, authenticated sessions. Use them only on systems you own or have explicit written permission to test. Hosting decoys in the wild against unconsenting users is criminal in every jurisdiction this course is taught in.
SECTION 23. Important Notes
Common beginner mistakes
- ●Stopping at "page is framable" without demonstrating a sensitive action being hijacked. Triagers reject these.
- ●Confusing Clickjacking with CSRF (the differences are in sections 1, 5, and 23).
- ●Forgetting to test alignment at opacity 0.5 before delivering at 0.0001.
- ●Not exploring URL prefills that convert a click into a meaningful state change.
- ●Ignoring multistep variants when the target has confirmation modals.
- ●Reporting Clickjacking on logout or other no-impact endpoints.
Pentester tips
- ●Map every authenticated state-changing action before crafting decoys.
- ●Use Burp's right-click "Generate Clickjacking PoC" to seed templates.
- ●Confirm in multiple browsers (Chrome, Firefox, Safari). Header enforcement varies subtly.
- ●Build a polished decoy library ("Free Phone", "Newsletter Unsubscribe", "Watch the Match Live"). The polish drives click-through.
- ●Save your PoC HTML with comments documenting the target coordinates and tested browser versions.
Bug bounty tips
- ●OAuth consent screens are the highest-paying Clickjacking targets (Coinbase $5,000 at https://hackerone.com/reports/65825 is the canonical example).
- ●Combine with prefilled URL params to demonstrate real account takeover, not just UI redress.
- ●Chain with DOM-XSS or self-XSS for compound impact and higher payouts.
- ●Admin panel Clickjacking on destructive endpoints (delete, ban, refund) consistently lands in the medium-to-critical range.
- ●Always include a hosted PoC URL and a screenshot/video showing the click and the resulting state change.
Red team tips
- ●Clickjacking is quiet: no malware, no exploit, no credentials stolen.
- ●Useful for low-noise initial access via OAuth grants to attacker-controlled apps.
- ●Combines naturally with phishing infrastructure.
- ●Cleanup is automatic: one click and the attack is complete; nothing left running.
Defender tips
- ●Set frame-protection headers from a single central middleware. Per-controller settings are how regressions happen.
- ●SAST rules: flag `xframe_options_exempt`, `frameOptions().disable()`, missing helmet in Node, missing CSP frame-ancestors in templates.
- ●CSP report-uri/report-to collects framing attempts in production -- treat any frame-ancestors violation as a near-miss.
- ●Enforce headers at the edge (CDN/WAF) as the final safety net.
Things to remember during exams
- ●CWE-1021, OWASP A05:2021.
- ●Primary defense: `X-Frame-Options: DENY` + `CSP frame-ancestors 'none'`.
- ●CSRF tokens do NOT stop Clickjacking.
- ●Sandbox attribute defeats JS frame busters.
- ●Multistep aligns decoys over consecutive buttons.
Frequently confused concepts
- ●Clickjacking vs CSRF: Clickjacking needs a click on a misdirected element; CSRF needs no click and uses background requests.
- ●Clickjacking vs XSS: XSS injects code into a page; Clickjacking overlays a real page on top of a fake one. They can chain.
- ●X-Frame-Options vs CSP frame-ancestors: both block framing; the CSP version is modern and preferred. Use both.
- ●Frame buster vs frame protection: a frame buster is JavaScript (bypassable); frame protection is an HTTP header (not bypassable by sandbox).
- ●Likejacking vs Clickjacking: likejacking is the social-media specific variant of Clickjacking; the technique is identical.
Interview tips
- ●Explain Clickjacking with the z-index / opacity / iframe sentence: invisible target iframe on top, visible decoy underneath.
- ●Cite the 2008 Adobe Flash disclosure as the origin and the Coinbase OAuth report ($5k) as a modern paid example.
- ●Mention `X-Frame-Options: DENY` and `CSP frame-ancestors 'none'` as the canonical defense pair.
- ●Explain why CSRF tokens do not help (the request is generated by the legitimate page with its own valid token).
- ●Be able to sketch the z-index stack on a whiteboard.
Key takeaways
- ●Clickjacking abuses the browser's layering and hit-testing, not server code.
- ●CSRF tokens and SameSite cookies do not stop it.
- ●The fix is one HTTP header; the cost of forgetting it is one misdirected click.
- ●Bug bounty payouts range from low (likejacking) to critical (admin actions, OAuth grants).
- ●Real disclosed reports paying $5,000+ exist in 2026 -- this is not a museum bug.
SECTION 24. Final Word from Your Instructor
You finished the Clickjacking course. You now know more about this bug class than most working developers, and enough to find it, exploit it, and fix it in any codebase.
Here is the short version.
Clickjacking happens because browsers let any page frame any other page by default. The attacker uses CSS to place a visible decoy on top of the framed target, then drops the iframe's opacity so the user sees only the decoy. The user clicks. The browser delivers the click to the iframe. The real target executes the action in the user's authenticated session. No code was injected, no credentials were stolen, no CSRF token was forged. The cookie was simply attached automatically because the target page is loaded inside the user's browser.
The defense is one HTTP header per page. `Content-Security-Policy: frame-ancestors 'none'` is the modern form. `X-Frame-Options: DENY` is the legacy fallback. Set both. Apply through central middleware so a future developer cannot regress one route. SameSite cookies and CSRF tokens are useful for other attacks; they are not the answer here.
On the offensive side, the workflow is short. Load the target inside an iframe. If it renders, you are in business. Measure the coordinates of a sensitive button. Build the decoy. Test at opacity 0.5. Ship at 0.0001. Combine with a prefilled URL parameter to turn the meaningless click into a meaningful state change. Combine with sandbox to defeat the JS frame buster. Combine with DOM-XSS to upgrade from action-hijack to code execution. Combine with OAuth to grant persistent third-party access.
The Coinbase report at https://hackerone.com/reports/65825 paid $5,000 for OAuth Clickjacking. The WakaTime double-Clickjacking on OAuth, the TikTok developer-app deletion, the Imgur self-XSS + Clickjacking chain, the X (Twitter) viral DM Clickjacking, the Yelp business-page hijacks: all real, all disclosed, all preventable with one header.
When you see a sensitive page, ask: what does `curl -sI` return? If the headers are missing, you have a finding. Demonstrate impact. Write it up. Submit.
Stay curious. Stay ethical. Verify scope before you touch anything.
Go hunt.