Directives

Injection - XSS

Le Cross-Site Scripting, également appelé XSS, est un type de vulnérabilité par injection qui conduit à l'exécution d'un script contrôlé par un attaquant dans le navigateur d'un autre utilisateur. Le XSS peut aussi être considéré comme une vulnérabilité d'injection HTML/JavaScript.

L'impact d'une vulnérabilité XSS dépend fortement du contexte dans lequel elle se trouve. Il peut aller de l'extraction d'informations sur la page où le script est exécuté à la modification de l'état de la page pour effectuer des actions au nom de la victime.

Examinons les types de XSS que vous pouvez rencontrer.

Types de XSS

Les attaques XSS peuvent être classées en plusieurs catégories pour faciliter leur distinction. Elles sont classées selon la manière dont la charge utile (payload) est transmise et l'emplacement du point d'entrée.

Vecteur de transmission de la charge utile (Stocké vs Reflété)

Il existe deux manières pour un attaquant de transmettre une charge utile XSS :

  • XSS stocké : via des données contrôlées par l'utilisateur et stockées, par exemple, dans une base de données, puis restituées à d'autres utilisateurs
  • XSS réfléchi : via une charge utile fournie par l'utilisateur et transmise par l'URL ou la chaîne de requête, sur laquelle l'utilisateur clique

La distinction essentielle est qu'un XSS réfléchi dépend généralement de l'interaction de l'utilisateur et n'affecte que celui qui ouvre le lien contenant la charge utile malveillante. En revanche, un XSS stocké peut être exécuté contre un ou plusieurs utilisateurs par la simple consultation de pages affichant la charge utile.

Emplacement de la charge utile (DOM vs Non-DOM)

L'emplacement où la charge utile est injectée détermine si la vulnérabilité est classée comme une vulnérabilité « DOM » ou non. Cela fait référence à la distinction entre les endroits où la charge utile est rendue :

  • XSS non-DOM : la charge utile est rendue à l'intérieur du HTML, que ce soit dans une balise ou un attribut
  • XSS DOM : la charge utile est rendue à l'intérieur du JavaScript, comme dans une balise `<script>` ou un gestionnaire d'événement tel que `onclick=""`

XSS - Principes de défense

Dans cette section, nous examinerons les principes fondamentaux de la défense contre les XSS. Il est essentiel d'en comprendre les bases, mais en pratique, vous devriez vous appuyer sur votre bibliothèque de templating pour 99 % de votre protection contre les XSS.

Lorsque vous écrivez des modèles (templates) destinés à être rendus en balisage ou en code exécuté dans un navigateur, la clé de la protection contre les XSS est l'encodage. Dans ce contexte, l'encodage consiste à transformer une séquence de caractères en un format traité de manière spécifique par l'interpréteur.

Cependant, le type d'encodage à utiliser dépend de l'emplacement ou du contexte dans lequel les données seront utilisées.

  • À l'intérieur d'une balise, comme `<div>Saisie utilisateur ici</div>` : **Encodage HTML**
  • À l'intérieur d'un attribut, comme `<input placeholder="Saisie utilisateur ici"></input>` : **Encodage d'attribut**
  • À l'intérieur de JavaScript, comme `<script>x = "Saisie utilisateur ici";</script>` : **Encodage JavaScript**

Certains frameworks délaissent l'encodage comme moyen de défense principal au profit de la désinfection (sanitization) pour nettoyer une valeur de tout contenu potentiellement dangereux. Il s'agit d'un processus beaucoup plus complexe comportant de nombreux cas particuliers à prendre en compte. Il n'est pas recommandé d'implémenter vos propres routines de désinfection.

Exemples

Examinons quelques exemples dans différents langages pour voir comment cela se traduit concrètement.

C# - Non sécurisé : Razor

Si un objet `IHtmlContent` est précédé d'un `@`, la valeur est directement insérée dans le modèle sans aucun encodage.

<!--- NON SÉCURISÉ : Le htmlSnippet sera interprété sans aucune protection --->
@Html.Raw(htmlSnippet)

C# - Sécurisé : Razor

Par défaut, toute `string` précédée d'un `@` est échappée en HTML dans les modèles Razor.

<!--- SÉCURISÉ : Le htmlSnippet sera échappé en HTML --->
@htmlSnippet

Java - Sécurisé : JSP

When using `c:out`, it XML escape by default (Which can be changed with the property `escapeXml`), which protects against XSS in a HTML context, but not in other contexts.

<div><c:out value="<%= author %>" /></div>

Java - Sécurisé : (fnxml)

De manière similaire, vous pouvez appeler directement `fn:escapeXml`, qui appliquera un échappement XML à l'entrée fournie. Cela ne protège également que dans un contexte HTML.

<div>${fn:escapeXml(author)}</div>

Javascript - Non sécurisé : innerHtml dans Angular

En spécifiant la propriété `innerHTML`, comme son nom l'indique, vous vous exposez à un risque de faille XSS en raison de la désactivation de l'encodage de sortie.

<!--- NON SÉCURISÉ : Le htmlSnippet sera interprété sans aucun encodage --->
<p [innerHTML]="htmlSnippet"></p>

Javascript - Sécurisé : Interpolation dans Angular

L'interpolation de texte d'Angular utilisant des doubles accolades (`{{` et `}}`) échappe le code HTML de sa sortie, protégeant ainsi contre les failles XSS.

<!--- SÉCURISÉ : Le htmlSnippet sera encodé puis interprété --->
<p>{{htmlSnippet}}</p>

Javascript - Non sécurisé : dangerousInnerHtml dans React

L'utilisation de la propriété `dangerouslySetInnerHTML`, comme son nom l'indique, vous expose à un risque de faille XSS en désactivant l'encodage de sortie.

<!--- NON SÉCURISÉ : Comme son nom l'indique, l'attribut dangerouslySetInnerHTML est dangereux car il n'échappe pas la sortie --->
<div dangerouslySetInnerHTML={{ __html: htmlSnippet }} />;

Javascript - Sécurisé : Interpolation React

L'interpolation de texte dans React via les accolades (`{` et `}`) échappe automatiquement le code HTML en sortie, protégeant ainsi contre les failles XSS.

<!--- SÉCURISÉ : Le htmlSnippet sera encodé puis interprété --->
<div>{htmlSnippet}</div>

Python - Non sécurisé : Django

L'utilisation du filtre `safe` dans un template Django désactive l'échappement automatique de la sortie, supprimant ainsi la protection contre les failles XSS.

<!--- NON SÉCURISÉ : Le htmlSnippet ne sera pas encodé en HTML --->
<div>{{ htmlSnippet | safe }}</div>

Python - Sécurisé : Django

L'interpolation de texte dans Django via les doubles accolades (`{{` et `}}`) échappe automatiquement le code HTML en sortie, protégeant ainsi contre les failles XSS.

<!--- SÉCURISÉ : Le htmlSnippet sera encodé en HTML --->
<div>{{ name }}</div>

‍

Slogan

Le codage sécurisé en pratique

Explorez nos directives de développement sécurisé pour comprendre et atténuer les vulnérabilités logicielles telles que l'OWASP Top 10, et plongez dans des missions de formation guidées pour vous exercer sur des simulations d'applications réelles.

Autres directives
Réserver une démo