technical

Bloquez le clickjacking avec frame-ancestors

MetricSpot vérifie X-Frame-Options ou CSP frame-ancestors. Ces en-têtes empêchent les attaquants d'intégrer votre site dans une iframe invisible pour piéger les clics.

Ce que vérifie ce contrôle

Inspecte les en-têtes de réponse à la recherche de l’un de ceux-ci :

  • X-Frame-Options: DENY ou X-Frame-Options: SAMEORIGIN
  • Content-Security-Policy: frame-ancestors 'none' ou frame-ancestors 'self'

Le contrôle échoue lorsqu’aucun n’est présent et qu’un attaquant pourrait intégrer votre page dans une iframe invisible sur un site malveillant.

Pourquoi c’est important

Le clickjacking est une attaque par habillage d’interface : l’attaquant charge votre site dans une iframe transparente posée sur un bouton qui paraît innocent (« iPad gratuit ! Cliquez ici »). Le clic de l’utilisateur tombe en réalité sur un vrai bouton dans votre iframe — envoi d’un paiement, changement de mot de passe, transfert de fonds.

  • L’attaque fonctionne contre toute session connectée. Si un utilisateur est connecté à votre site dans un autre onglet, l’iframe hérite des cookies de session, donc le clic s’exécute en tant que cet utilisateur.
  • Elle a déjà été utilisée contre des sites bancaires, des réseaux sociaux et des tableaux d’administration. Les flux OAuth et les pages d’enrôlement 2FA ont été touchés.
  • Le correctif tient en un en-tête. Les navigateurs refusent d’afficher votre page dans une iframe lorsque l’en-tête est présent — l’attaque devient impossible.

La protection contre l’intégration en iframe est la mitigation la moins chère en sécurité web : un en-tête de réponse par page, aucun changement de code, aucun coût de performance.

Comment le corriger

Choisissez l’un des deux mécanismes. Les navigateurs modernes préfèrent CSP frame-ancestors ; X-Frame-Options est l’en-tête historique qui fonctionne aussi dans les anciens navigateurs. Envoyez les deux pour une couverture maximale — ils ne se contredisent pas.

Refuser toute intégration (recommandé pour les sites non destinés à être intégrés) :

Content-Security-Policy: frame-ancestors 'none'
X-Frame-Options: DENY

Autoriser l’intégration uniquement depuis votre propre origine :

Content-Security-Policy: frame-ancestors 'self'
X-Frame-Options: SAMEORIGIN

Autoriser l’intégration depuis des origines de confiance spécifiques (seul CSP le supporte — X-Frame-Options ne peut pas lister plusieurs domaines) :

Content-Security-Policy: frame-ancestors 'self' https://partner.example.com

nginx :

add_header Content-Security-Policy "frame-ancestors 'none'" always;
add_header X-Frame-Options "DENY" always;

Le drapeau always est crucial — sans lui, nginx omet l’en-tête sur les réponses d’erreur.

Apache :

Header always set Content-Security-Policy "frame-ancestors 'none'"
Header always set X-Frame-Options "DENY"

Caddy :

header {
  Content-Security-Policy "frame-ancestors 'none'"
  X-Frame-Options "DENY"
}

Cloudflare — Rules → Transform Rules → Modify Response Header, ajoutez les deux en-têtes globalement. Ou utilisez le produit Page Shield pour un contrôle au niveau WAF.

Next.js (next.config.js) :

module.exports = {
  async headers() {
    return [
      {
        source: "/(.*)",
        headers: [
          { key: "Content-Security-Policy", value: "frame-ancestors 'none'" },
          { key: "X-Frame-Options", value: "DENY" },
        ],
      },
    ];
  },
};

Express :

import helmet from "helmet";
app.use(helmet.frameguard({ action: "deny" }));
app.use(
  helmet.contentSecurityPolicy({
    directives: { frameAncestors: ["'none'"] },
  })
);

Testez-le :

curl -sI https://votredomaine.com/ | grep -iE 'frame'

Attendez-vous aux deux en-têtes, ou au moins à frame-ancestors. Essayez ensuite de l’intégrer dans une iframe en local pour confirmer que le navigateur refuse.

Questions fréquentes

Dois-je refuser toute intégration ou seulement autoriser même origine ?

Mettez frame-ancestors 'none' par défaut et ne relâchez que si vous avez activement besoin d’intégrer vos pages. La plupart des sites marketing, tableaux d’administration et applications ne devraient jamais être encadrés — et les fournisseurs OAuth (Google, Apple, Stripe) qui ont réellement besoin de l’intégration ont des flux d’embed bien définis qui n’exigent pas de relâcher votre CSP.

Et X-Frame-Options: ALLOW-FROM ?

Déprécié et non supporté par Chrome et Firefox. Utilisez Content-Security-Policy: frame-ancestors à la place — il accepte plusieurs origines et fonctionne dans tous les navigateurs modernes.

Cela casse-t-il PageSpeed Insights de Google ou un autre outil ?

Non. Ces outils récupèrent la page directement, pas en iframe. L’en-tête n’affecte que l’intégration en iframe.

Sources

Dernière mise à jour 2026-05-11