$npx -y skills add elementalsouls/Claude-BugHunter --skill hunt-clickjackingHunt Clickjacking — missing X-Frame-Options / CSP frame-ancestors lets an attacker embed the target page in an invisible iframe and trick victims into clicking buttons they cannot see (UI redressing). Targets: login flows, money transfers, account settings, OAuth confirmation pag
| 1 | ## What is Clickjacking |
| 2 | |
| 3 | Clickjacking (UI Redressing) lets an attacker load a target page inside a transparent iframe on a malicious site. The victim sees the attacker's decoy UI but clicks the hidden target UI beneath it. No JavaScript on the target is required. |
| 4 | |
| 5 | **Highest-value targets:** |
| 6 | - Login / authentication pages — force login with attacker credentials |
| 7 | - Money transfer / checkout / "confirm payment" buttons |
| 8 | - Account settings (email change, password change, 2FA disable) |
| 9 | - OAuth / social-login "Authorize app" confirmation dialogs |
| 10 | - Admin actions (delete, promote user, change role) |
| 11 | |
| 12 | ## Protection Headers |
| 13 | |
| 14 | Two mechanisms prevent framing: |
| 15 | |
| 16 | ``` |
| 17 | X-Frame-Options: DENY # strongest — blocks all framing |
| 18 | X-Frame-Options: SAMEORIGIN # allows same-origin frames only |
| 19 | Content-Security-Policy: frame-ancestors 'none' # CSP equivalent of DENY |
| 20 | Content-Security-Policy: frame-ancestors 'self' # CSP equivalent of SAMEORIGIN |
| 21 | ``` |
| 22 | |
| 23 | If NEITHER is present, the page is frameable from any origin. |
| 24 | |
| 25 | ## How to Test |
| 26 | |
| 27 | Header-absence is the **trigger for investigation, not the finding**. Two steps: |
| 28 | |
| 29 | **Step 1 — Header check (screening).** Fetch the target page and inspect the response headers: |
| 30 | |
| 31 | ``` |
| 32 | curl -sI https://target.example/account/transfer | grep -iE 'x-frame-options|content-security-policy' |
| 33 | ``` |
| 34 | If BOTH `X-Frame-Options` and CSP `frame-ancestors` are absent, the page is a *candidate*. If either is present and restrictive (`DENY`/`SAMEORIGIN`/`frame-ancestors 'none'|'self'`), stop — it's protected. |
| 35 | |
| 36 | **Step 2 — Prove it actually frames and clicks (required for a real finding).** Build a minimal PoC and load it in a real browser: |
| 37 | |
| 38 | ```html |
| 39 | <!doctype html> |
| 40 | <h1>Win a prize — click below</h1> |
| 41 | <iframe src="https://target.example/account/transfer" |
| 42 | style="opacity:0.1;position:absolute;top:0;left:0;width:1000px;height:800px"></iframe> |
| 43 | ``` |
| 44 | Confirm ALL of the following, or it is not exploitable: |
| 45 | - The page **actually renders inside the iframe** (no framebusting JS that blanks/redirects it — e.g. `if(top!==self)` breakout, or a `Sec-Fetch-Dest`/JS frame check). |
| 46 | - The **sensitive action still works while framed** — critically, the action must succeed *cross-site*. If it relies on a session cookie set `SameSite=Lax` or `SameSite=Strict` (the modern default), the cookie is **not** sent on the cross-site framed request, and the clickjack fails. Verify the victim's authenticated state carries into the frame. |
| 47 | - The target is a **state-changing action** (transfer, settings/email/password change, 2FA disable, OAuth authorize, admin action), not a read-only page. |
| 48 | |
| 49 | **Strategy:** target the most sensitive action pages first — severity scales directly with what the victim is tricked into doing. |
| 50 | |
| 51 | ## False Positives |
| 52 | |
| 53 | - Public, read-only pages (home/marketing) lacking frame protection are low/informational — no sensitive action to redress. |
| 54 | - APIs and non-HTML endpoints (JSON, images) are not clickjacking targets. |
| 55 | - **Header-absence alone is NOT a finding.** SameSite cookies, framebusting JS, or the lack of any sensitive framed action can each fully defeat it — which is why Step 2 is mandatory. |
| 56 | |
| 57 | ## Proof Requirements |
| 58 | |
| 59 | A valid clickjacking report shows: (1) the target page rendered inside an attacker-controlled iframe in a real browser, (2) a sensitive state-changing action reachable by a framed click while the victim is authenticated (cookies survive the cross-site context), and (3) a screenshot/recording of the overlay. Reporting missing headers with no working frame PoC is a documentation-quality issue, not a vulnerability. |