Clickjacking et en-têtes de sécurité HTTP (CSP, X-Frame-Options)
Certaines failles ne s’attaquent ni au serveur ni aux scripts : elles jouent sur ce que l’utilisateur voit. C’est le cas du clickjacking, où l’on pousse quelqu’un à cliquer sur un bouton légitime sans qu’il s’en rende compte. La bonne nouvelle : une famille d’en-têtes HTTP, ajoutés par le serveur, offre une défense efficace contre cette faille et contre beaucoup d’autres du chapitre. Cette leçon boucle le chapitre 4 en vous les présentant.
Rappel légal
Tromper un utilisateur pour qu’il déclenche une action sur un site réel est une atteinte à autrui, et sans autorisation écrite et périmètre défini, c’est une infraction (articles 323-1 à 323-3-1 du Code pénal). Les expériences de cette leçon se limitent à l’analyse des en-têtes de votre application d’entraînement locale et à des tests dans un laboratoire autorisé.
Le clickjacking : le principe
Les navigateurs permettent à une page d’en inclure une autre dans un cadre (une iframe). C’est utile : vidéos intégrées, cartes, formulaires de paiement. Mais cela ouvre une possibilité : une page piégée peut inclure le vrai site dans un cadre transparent, placé au-dessus d’un faux contenu attractif (« Cliquez pour gagner »). La victime croit cliquer sur le faux bouton, mais son clic atterrit sur un vrai bouton du site, par exemple « Supprimer le compte » ou « Autoriser ».
Analogie : une vitre transparente posée sur un distributeur de billets. Vous croyez appuyer sur la touche « Valider » du dessin, mais votre doigt appuie sur la vraie touche de la machine en dessous.
Comme dans le CSRF, la victime est connectée et le site reçoit une action légitime en apparence. Mais ici, l’action est réellement cliquée par l’utilisateur : un jeton anti-CSRF ne protège donc pas contre le clickjacking. Il faut une défense spécifique.
Comment tester si un site peut être mis en cadre
Le test ne nécessite aucune page piégée : il suffit d’examiner les en-têtes de la réponse HTTP. Deux mécanismes interdisent à d’autres sites d’inclure la page :
| En-tête | Rôle | Valeurs courantes |
|---|---|---|
X-Frame-Options | Interdit ou limite la mise en cadre de la page (mécanisme ancien, très répandu) | DENY (jamais), SAMEORIGIN (seulement par le même site) |
Content-Security-Policy avec la directive frame-ancestors | Définit précisément quels sites ont le droit d’inclure la page (mécanisme moderne, plus flexible) | 'none', 'self', ou une liste d’origines |
Si aucun des deux n’est présent sur une page sensible, la page peut être incluse n’importe où : constat de clickjacking potentiel. Les pages sans action sensible (page d’information statique) sont moins préoccupantes.
La Content-Security-Policy (CSP)
La CSP est l’un des outils les plus puissants du web moderne. C’est une liste de règles, envoyée par le serveur dans un en-tête, qui indique au navigateur ce qu’il a le droit de charger et d’exécuter : d’où viennent les scripts, les images, les feuilles de style, quels sites peuvent inclure la page… Une règle simple :
Content-Security-Policy: default-src 'self'; script-src 'self'; frame-ancestors 'none'; object-src 'none'; base-uri 'self'
Cette politique dit : par défaut, ne charger des ressources que depuis le site lui-même ; n’exécuter de scripts que ceux du site ; interdire toute mise en cadre ; interdire les objets embarqués ; restreindre l’adresse de base. Une page protégée ainsi empêche, en pratique, l’exécution de scripts injectés (XSS) venant d’une source non autorisée.
Points d’attention pour l’auditeur :
- Une CSP qui autorise les scripts « en ligne » sans restriction (
'unsafe-inline') perd l’essentiel de son intérêt contre le XSS. - Une CSP qui autorise des domaines très larges (ou « tout », avec une étoile) est très peu protectrice.
- La CSP est une défense en profondeur : elle ne remplace pas l’encodage de sortie.
- Un mode « rapport seul » permet de tester une politique sans bloquer, utile lors d’un déploiement progressif.
La documentation complète figure sur developer.mozilla.org, rubrique des en-têtes HTTP.
Les autres en-têtes de sécurité à connaître
| En-tête | Protection |
|---|---|
Strict-Transport-Security | Force le navigateur à n’utiliser que HTTPS pour ce site pendant une durée donnée |
X-Content-Type-Options: nosniff | Empêche le navigateur de « deviner » un autre type de contenu que celui déclaré |
Referrer-Policy | Limite les informations d’origine transmises dans l’en-tête de provenance |
Permissions-Policy | Restreint l’accès aux fonctionnalités du navigateur (caméra, géolocalisation…) |
Cross-Origin-Opener-Policy et voisins | Renforcent l’isolation entre pages d’origines différentes |
Ces en-têtes ne corrigent pas une faille du code, mais ils réduisent la surface d’attaque et l’impact d’éventuelles failles. Un audit vérifie leur présence et leur pertinence, sans les surévaluer : l’absence d’un en-tête est rarement un constat « critique » à elle seule, mais s’inscrit dans une approche de défense en profondeur.
Auditer les en-têtes en pratique
- Chargez une page de votre application d’entraînement avec le proxy actif.
- Dans l’historique, ouvrez la réponse et lisez ses en-têtes.
- Pour chaque en-tête du tableau ci-dessus, notez : présent ou absent ; si présent, valeur et pertinence.
- Vérifiez aussi les en-têtes inutiles qui divulguent des informations (version du serveur, technologie), dont nous reparlerons au chapitre 6.
Voici un extrait d’en-têtes de réponse bien configurés, à titre d’exemple générique :
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Content-Security-Policy: default-src 'self'; frame-ancestors 'none'
Referrer-Policy: strict-origin-when-cross-origin
Les valeurs dépendent de chaque application : une CSP trop stricte peut casser des fonctionnalités légitimes. Elle se met donc au point en testant, d’abord en mode rapport.
Astuce
Dans un rapport, formulez les recommandations d’en-têtes comme des améliorations proportionnées, avec leur justification (« la page de paiement peut être mise en cadre : ajouter frame-ancestors ou X-Frame-Options »), plutôt qu’une liste générique copiée d’un outil.
À vous de jouer
- Relevez les en-têtes de réponse de trois pages de votre application d’entraînement (accueil, connexion, une page de modification).
- Complétez un tableau avec les en-têtes du chapitre : présent, absent, valeur.
- Choisissez la page où l’absence de protection contre la mise en cadre est la plus préoccupante, et expliquez pourquoi.
- Rédigez une CSP minimale que vous recommanderiez pour cette application, et expliquez ce que chaque directive apporte.
Voir une solution
La page de modification d’informations (ou de suppression de compte) est la plus préoccupante : c’est là qu’un clic piégé pourrait avoir un effet. Un constat type : « La page de modification du profil peut être incluse dans un cadre par n’importe quel site (absence de X-Frame-Options et de frame-ancestors). Gravité faible à moyenne. Correction : Content-Security-Policy: frame-ancestors 'none' et X-Frame-Options: DENY. » CSP minimale possible : default-src 'self'; frame-ancestors 'none'; object-src 'none'; base-uri 'self'. Chaque directive limite une catégorie de chargement ou d’inclusion.
À retenir
- Le clickjacking trompe l’œil de l’utilisateur en superposant une page transparente à un faux contenu.
- Un jeton anti-CSRF ne protège pas contre lui : il faut interdire la mise en cadre avec
frame-ancestorsouX-Frame-Options. - La CSP définit ce que le navigateur peut charger ou exécuter ; elle limite l’impact d’un XSS sans remplacer l’encodage de sortie.
- Autres en-têtes utiles : HSTS,
nosniff,Referrer-Policy,Permissions-Policy. - Un audit d’en-têtes vérifie présence et pertinence, avec des recommandations proportionnées.
Les failles côté client n’ont plus de secret pour vous. Le chapitre suivant aborde une question plus subtile : l’application vérifie-t-elle bien que chacun ne fait que ce qu’il a le droit de faire ?