Web › Module 2 › Lesson 3
Clickjacking and Frame Abuse
A02: frame DENY on — X-Frame-Options / CSP.
Visual · clickjacking_frame
Clickjacking defense: 0.0.1:8769. X-Frame-Options / CSP frame-ancestors.
Opening
Clickjacking is not “iframe exists.” It is your UI acting under someone else’s page without the user meaning to.
An attacker hosts a page that iframes your site (or a sensitive flow) under a deceptive overlay. The victim thinks they click the attacker’s button; they actually confirm a transfer, follow, or settings change on your origin. That is UI redressing — classic when framing is allowed. OWASP Top 10:2025 A02 covers missing frame defenses as misconfiguration. This is ORIGINAL Cyberlium teaching.
1. Mechanism: framed sensitive UI + deceptive overlay = unintended action
Browsers allow embedding unless headers or CSP say otherwise. If your change-password or confirm-pay page can be framed, a malicious parent can align invisible controls under fake buttons. Same-site cookies may still send. The victim’s intent is hijacked; the request looks legitimate to your server. Finding language: “Sensitive flows frameable; missing X-Frame-Options / frame-ancestors.” Fix language: “DENY or SAMEORIGIN; CSP frame-ancestors 'none' or allowlist; confirm critical actions with re-auth when needed.”
Command guide
A02 Misconfig — Mechanism
═══ INSTALL ═══
Linux (Debian/Ubuntu):
Command — copy this
sudo apt install curl
macOS: Built-in
Windows: Built-in (PowerShell: Invoke-WebRequest)
═══ COMMANDS ═══
Command — copy this
SAFE="http://127.0.0.1:8769"
Command — copy this
curl -sS -m 3 -I "$SAFE/" | grep -i -E "x-frame-options|content-security-policy|frame-ancestors"
2. Defenses: X-Frame-Options and CSP frame-ancestors
X-Frame-Options: DENY blocks all framing; SAMEORIGIN allows same-origin frames. CSP frame-ancestors is the modern directive and can allowlist specific parents. Prefer setting both during transition if your stack needs it — test YOUR app. frame-ancestors 'none' is the strict literacy default for sensitive pages. JavaScript frame-busting alone is historically brittle; headers/CSP are the shipping control. Do not teach “bypass framebust” cookbooks here.
Command guide
A02 Misconfig — Defenses
═══ INSTALL ═══
Linux (Debian/Ubuntu):
Command — copy this
sudo apt install curl
macOS: Built-in
Windows: Built-in (PowerShell: Invoke-WebRequest)
═══ COMMANDS ═══
Command — copy this
SAFE="http://127.0.0.1:8769"
Command — copy this
curl -sS -m 3 -I "$SAFE/broken" | grep -i -E "x-frame-options|frame-ancestors" curl -sS -m 3 -I "$SAFE/hard" | grep -i -E "x-frame-options|frame-ancestors"
3. What is out: UI-redress kits and foreign targets
Building a transparent overlay against a live bank, school portal, or classmate app is unauthorized social/technical abuse. Cyberlium demos: identify DEMO, then serve a toy page on 127.0.0.1:8769 with DENY, curl -I the child path, record the header. That is enough. No BeEF. No hydra of 192.168.0.1. No “victim lure” pages aimed at humans outside written people-scope (this course has none).
Command guide
A02 Misconfig — What is out
═══ INSTALL ═══
Linux (Debian/Ubuntu):
Command — copy this
sudo apt install curl
macOS: Built-in
Windows: Built-in (PowerShell: Invoke-WebRequest)
═══ COMMANDS ═══
Command — copy this
SAFE="http://127.0.0.1:8769"
Command — copy this
curl -sS -m 3 -I "$SAFE/" | head -n 16
4. Tie-back to headers lesson and A02 checklist
Clickjacking defense is one line on the A02 hardening checklist next to CSP and nosniff. Missing it is misconfiguration even when the rest of the app is careful. Record whether YOUR sensitive routes send frame defenses.
5. What you record
Date (UTC). Clickjacking = framed UI + deception. Defenses: X-Frame-Options / frame-ancestors. curl -I observation on DEMO or SAFE 127.0.0.1:8769. Ethics: NEVER foreign UI-redress; NEVER BeEF; NEVER hydra/nmap the LAN. Path: $HOME/cyberlium-lab/a02-clickjack-notes.txt, chmod 600. Legal: original Cyberlium — not official OWASP certification.
6. Wrong vs right: redress kits vs frame deny on YOUR pages
Worked failure — same iframe tag, opposite target. Right never needs a victim lure.
Wrong
Overlay a bank or classmate app. Hydra the home router. Ship clickjack PoC kits. Skip headers and “test on production users.”
Right
Identify DEMO; serve toy pages on 127.0.0.1:8769 with DENY; curl -I; lock a02-clickjack-notes.txt. Next: Lab — Harden Config on Loopback.
Create parent and child pages locally. Child sets DENY. curl -I proves the header. chmod 600.
Command guide
a02_clickjack_demo.sh — DEMO identify + frame DENY on 127.0.0.1:8769
═══ INSTALL ═══
Linux (Debian/Ubuntu):
Command — copy this
sudo apt install curl sudo apt install nmap sudo apt install python3
macOS:
Command — copy this
brew install nmap brew install python3
Windows: Built-in (PowerShell: Invoke-WebRequest)
Command — copy this
choco install nmap # or download https://nmap.org/download.html
Download https://python.org/downloads/
═══ COMMANDS ═══
Command — copy this
cd "$HOME/cyberlium-lab"
Command — copy this
SAFE="http://127.0.0.1:8769"
Command — copy this
cat > a02_clickjack_demo.py << 'PY'
from http.server import BaseHTTPRequestHandler, HTTPServer
HOST = "127.0.0.1" # bind only — never 0.0.0.0, never argv
PORT = 8769
if HOST != "127.0.0.1":
raise SystemExit("refusing non-loopback bind")
CHILD = b"<html><body><h1>sensitive toy action</h1><button>Confirm</button></body></html>"
PARENT = b"""<html><body><h1>local parent</h1>
<iframe src="http://127.0.0.1:8769/child" width="400" height="200"></iframe>
</body></html>"""
class H(BaseHTTPRequestHandler):
def do_GET(self):
if self.path.startswith("/child"):
body = CHILD
self.send_response(200)
self.send_header("Content-Type", "text/html; charset=utf-8")
self.send_header("X-Frame-Options", "DENY")
self.send_header("Content-Security-Policy", "frame-ancestors 'none'")
else:
body = PARENT
self.send_response(200)
self.send_header("Content-Type", "text/html; charset=utf-8")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
print("bind", HOST, PORT)
print("demo_writeup_url http://192.168.0.1/")
print("if 192.168.0.1 is a router, curl -I", f"http://{HOST}:{PORT}/child")
print("ethics: NEVER foreign clickjack kits; NEVER BeEF; NEVER hydra/nmap the LAN")
print("legal: original Cyberlium — not official OWASP certification")
HTTPServer((HOST, PORT), H).serve_forever()
PYCommand — copy this
cat > a02_clickjack_practical.sh << 'SH' SAFE="http://127.0.0.1:8769" curl -sS -I "$SAFE/child" | grep -i -E 'HTTP/|X-Frame-Options|Content-Security-Policy' SH
Command — copy this
{Mission: a02-clickjack-notes.txt in cyberlium-lab (mode 600)
1) 0.0.1:8769.2) curl -I SAFE /child; record DENY / frame-ancestors; fill notes chmod 600. 3) Ethics: no foreign kits, no hydra/nmap of the LAN.
Stuck? Ask Cyberlium AI Mentor
If “I need a real victim page to learn clickjacking” still feels true, ask for a hint — not a lure kit. Try: "Hint only: how framing enables UI redress, which curl -I lines prove DENY on 127.0.0.1:8769, and where locked a02-clickjack-notes.txt lives?"
You now treat clickjacking as frame abuse stopped by X-Frame-Options / CSP frame-ancestors — an A02 posture control — with curl on YOUR lab or SAFE loopback and locked notes. Original Cyberlium — not official OWASP certification. Next — Lab — Harden Config on Loopback.
Knowledge Check
APPLY: A sensitive confirm page can be iframed by any origin. What failed, and what do you ship?
Multiple choice
Knowledge Check
APPLY: True or False: JavaScript frame-busting alone is the preferred modern defense versus CSP frame-ancestors.
True or False
Knowledge Check
APPLY: curl http://192.168.0.1/ shows Huawei Router Admin. What do you do?
Multiple choice