Si un visiteur peut déposer sur votre page un texte que d'autres verront, et que ce texte n'est pas échappé, il peut y déposer un script à la place. Celui-ci tourne au nom de votre site, avec la session de votre visiteur, et peut tout ce que ce visiteur peut faire.

D'où cela vient

  • Un commentaire, un nom, un avis - tout ce qu'une personne tape et qu'une autre voit.
  • Un paramètre d'URL réimprimé sur la page, c'est-à-dire le champ de recherche de presque tous les sites.
  • Le nom d'un fichier déposé.
  • Des données venues d'une API que vous ne maîtrisez pas.

L'habitude

Échappez à la SORTIE, chaque fois, dans le contexte où vous écrivez. Pas à l'entrée : la même donnée peut être imprimée dans du HTML, dans un attribut et dans du JavaScript, et chacun demande un échappement différent.

echo htmlspecialchars($name, ENT_QUOTES, 'UTF-8');
  • Dans du texte HTML - htmlspecialchars avec ENT_QUOTES.
  • Dans un attribut - la même chose, et mettez toujours l'attribut entre guillemets.
  • Dans du JavaScript - json_encode, jamais de concaténation de chaînes.
  • Dans une URL - urlencode.
Échapper au moment de l'ENREGISTREMENT est l'erreur classique : la même valeur doit ensuite être dééchappée pour un courriel, un export ou une API, et l'un de ces chemins oublie toujours. Stockez ce qui a été tapé ; échappez au moment de l'affichage.

Une deuxième couche

add_header Content-Security-Policy "default-src 'self'; script-src 'self'" always;

La CSP dit au navigateur de n'exécuter des scripts que depuis votre propre origine : un script en ligne injecté ne s'exécute donc pas, même si l'un passe. Mettez-la d'abord en mode rapport seul, sinon vous casserez votre propre page.

Testez-le

Mettez un marqueur inoffensif dans chaque champ et regardez la SOURCE de la page qui l'affiche. Voir votre marqueur comme du texte est correct ; le voir comme une balise, c'est la faille.

Un moteur de gabarits qui échappe par défaut supprime l'essentiel de cette famille de failles. Si le vôtre le fait, n'attrapez pas l'aide « afficher brut » sans une raison défendable.