September 3, 2026
You Thought You Were Clicking a Button. You Weren’t. — A Beginner’s Guide to Clickjacking
By // l1m1nal_3ntr0py

By // l1m1nal_3ntr0py
4 min read
Imagine you walk into a shop and see a big sign that says "Click here to win a free gift!" You tap it excitedly. But behind that sign — invisible to you — was a different button entirely. One that just transferred all your money to someone else.
You thought you were claiming a prize. You were signing a blank cheque.
That is clickjacking. And it happens on real websites, to real people, every day.
What Is Clickjacking?
Clickjacking — also called UI redressing — is an attack where a victim is tricked into clicking something they cannot see. The attacker places an invisible webpage on top of a fake one. The victim sees the fake page. But their click lands on the real page underneath.
The result? The victim unknowingly performs an action on a real website — liking a post, changing an email address, confirming a purchase, or deleting an account — without ever realising it.
How Is It Different From CSRF?
You might have heard of CSRF — Cross-Site Request Forgery. Both attacks trick users into performing unintended actions. But they work very differently.
CSRF works silently in the background — no user interaction needed. The victim doesn't click anything. The attack fires automatically.
Clickjacking requires the victim to actually click something. The click is real. The victim genuinely moved their mouse and pressed the button. They just had no idea what they were really clicking.
This distinction matters for defence — which we will get to later.
The Invisible Layer — How It Actually Works
The technical heart of clickjacking is something called an iframe.
An iframe is an HTML element that loads one webpage inside another. You see iframes all the time — YouTube videos embedded in news articles, Google Maps inside restaurant websites. Completely normal and legitimate.
Attackers abuse this feature. Here is what a basic clickjacking attack looks like:
html
<head>
<style>
#target_website {
position: relative;
width: 128px;
height: 128px;
opacity: 0.00001;
z-index: 2;
}
#decoy_website {
position: absolute;
width: 300px;
height: 400px;
z-index: 1;
}
</style>
</head>
<body>
<div id="decoy_website">
...fake content here...
</div>
<iframe id="target_website" src="https://vulnerable-website.com">
</iframe>
</body><head>
<style>
#target_website {
position: relative;
width: 128px;
height: 128px;
opacity: 0.00001;
z-index: 2;
}
#decoy_website {
position: absolute;
width: 300px;
height: 400px;
z-index: 1;
}
</style>
</head>
<body>
<div id="decoy_website">
...fake content here...
</div>
<iframe id="target_website" src="https://vulnerable-website.com">
</iframe>
</body>Let me break down what each part does:
opacity: 0.00001 — This makes the iframe almost completely invisible. The victim cannot see it. But it is there, sitting on top of the decoy page, waiting.
z-index: 2 — This controls the stacking order. The iframe sits above the fake page. So when the victim clicks — even though they see the fake page — their click hits the iframe first.
position: absolute / relative — These CSS values ensure the iframe and the decoy page overlap precisely. The attacker carefully aligns the invisible button on the real site with the fake text on the decoy site.
The result — the victim sees "Click here to claim your prize!" They click it. But they actually clicked the "Delete my account" button on a bank website loaded invisibly behind it.
A Real World Example — Prefilled Form Attack
Here is a more targeted version of clickjacking that is surprisingly common.
Many websites allow form fields to be pre-populated via URL parameters. For example:
Normal URL:
https://site.com/my-account
Attacker's modified URL:
https://site.com/my-account?email=attacker@evil.comNormal URL:
https://site.com/my-account
Attacker's modified URL:
https://site.com/my-account?email=attacker@evil.comWhen the victim visits the modified URL, the email field is already filled with the attacker's email address. All the victim has to do is click Submit — and they have just changed their account email to the attacker's address.
The attacker then overlays this pre-filled page inside an invisible iframe on a decoy website. The victim sees "Click here" and clicks. The form submits. Account hijacked.
The attacker never needed to know the victim's password. The victim handed over access themselves — without knowing it.
Clickjacking + DOM XSS — When It Gets Serious
Clickjacking on its own can cause real damage. Combined with a DOM XSS vulnerability — it becomes significantly more dangerous.
The attacker first finds a DOM XSS vulnerability in the target website. They craft a URL that triggers the XSS payload. Then they frame that URL inside an invisible iframe on the decoy page. When the victim clicks — the XSS executes.
This combination can steal session cookies, redirect users, or execute arbitrary JavaScript in the victim's browser — all triggered by a single innocent-looking click.
Multistep Clickjacking
Some actions require multiple clicks to complete — "Add to cart" then "Confirm order", or "Delete account" then "Yes, I'm sure."
Attackers solve this with multiple invisible layers — one decoy click for each required step. The victim clicks "Click me first!" then "Click me next!" thinking they are playing a game or claiming a reward. In reality they just completed a multi-step action on a real website.
How To Find It — Using Burp's Clickbandit
PortSwigger built a tool called Clickbandit directly into Burp Suite to make finding and demonstrating clickjacking easy.
Instead of manually writing CSS to align invisible iframes, Clickbandit automates the whole process — generating the attack page in seconds. It lets you visually confirm whether a target page is vulnerable to being framed.
To use it:
- Open Burp Suite
- Go to Burp menu → Clickbandit
- Follow the on-screen instructions to load the target page
- Clickbandit generates the attack page automatically
Prevention — How Developers Stop This
Two main server-side defences exist against clickjacking:
X-Frame-Options Header
This HTTP response header tells the browser whether the page is allowed to be loaded inside an iframe.
X-Frame-Options: denyX-Frame-Options: denyCompletely prevents the page from being framed by anyone.
X-Frame-Options: sameoriginX-Frame-Options: sameoriginOnly allows the page to be framed by pages on the same origin.
X-Frame-Options: allow-from https://trusted-website.comX-Frame-Options: allow-from https://trusted-website.comOnly allows framing from a specific trusted website.
Content Security Policy (CSP) — frame-ancestors
CSP is the modern, more flexible replacement for X-Frame-Options:
Content-Security-Policy: frame-ancestors 'none';Content-Security-Policy: frame-ancestors 'none';Nobody can frame this page — equivalent to X-Frame-Options: deny.
Content-Security-Policy: frame-ancestors 'self';Content-Security-Policy: frame-ancestors 'self';Only the same origin can frame this page.
Content-Security-Policy: frame-ancestors normal-website.com;Content-Security-Policy: frame-ancestors normal-website.com;Only the named website can frame this page.
CSP is preferred over X-Frame-Options because it is more flexible and better supported across modern browsers.
The Simple Version — What You Should Remember
Clickjacking works because:
- Browsers allow websites to load other websites inside iframes
- CSS can make those iframes invisible
- Clicks land on the invisible layer — not the visible one
It is stopped by:
- Telling the browser the page cannot be framed (
X-Frame-Options: deny) - Or using CSP to control who can frame your page
The attack requires user interaction — but that interaction is genuine. The victim really does click. They just cannot see what they are clicking.
Final Thought
The most elegant attacks are not the most complex ones. Clickjacking works because it turns something completely normal — clicking a button — into something dangerous. No malware. No exploits. No stolen passwords. Just a carefully placed invisible layer between a user and the truth.
The button was always there. The victim just could not see it.
Written by // l1m1nal_3ntr0py — documenting my cybersecurity journey from scratch
Follow my journey:
- 🐦 Twitter: @l1m1nal_3ntr0py
- 🐙 GitHub: l1m1nal-3ntr0py
- 🔓 HackerOne: nithig