Injection - XSS
Le Cross-Site Scripting, également connu sous le nom de XSS, est un autre type de vulnérabilité d'injection qui conduit à l'évaluation d'un script contrôlé par l'attaquant dans le navigateur d'un autre utilisateur. Le XSS peut également ê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 existe. Il peut s'agir de la possibilité d'extraire des informations de la page sur laquelle le script est exécuté et de modifier l'état de la page pour effectuer des actions en tant que victime sur la page.
Examinons les types de XSS que vous pouvez rencontrer.
Types de XSS
Les XSS peuvent être divisés en plusieurs catégories pour mieux les distinguer. Ils sont classés en fonction de la manière dont la charge utile est transmise et de l'endroit où se trouve le point d'entrée.
Vecteur de livraison de la charge utile (stockée ou réfléchie)
Un pirate peut transmettre une charge utile XSS de deux manières :
- XSS stocké: par le biais de données contrôlées par l'utilisateur et stockées, par exemple, dans une base de données où les données sont présentées à d'autres utilisateurs.
- XSS réfléchi: par le biais d'une charge utile fournie par l'utilisateur et transmise par l'URL/la chaîne de requête consultée par l'utilisateur.
La distinction essentielle est qu'un XSS réfléchi dépend généralement de l'interaction de l'utilisateur et n'a d'impact que sur l'utilisateur qui ouvre le lien contenant la charge utile malveillante. En revanche, un XSS stocké peut être exécuté à l'encontre d'un ou de plusieurs utilisateurs en ouvrant simplement des pages qui affichent la charge utile.
Emplacement de la charge utile (DOM ou non DOM)
L'endroit où une charge utile est injectée détermine si vous classez la vulnérabilité dans la catégorie des vulnérabilités "DOM" ou non. Il s'agit de la distinction entre l'endroit où la charge utile est rendue :
- XSS non DOM: la charge utile est rendue à l'intérieur du code HTML, que ce soit à l'intérieur d'une balise ou d'un attribut.
- DOM XSS: The payload is rendered inside JavaScript, like a `<script>` tag, or an event handler such as `onclick=""`
XSS - Primitives de défense
Dans cette section, nous allons examiner les principes des primitives qui sous-tendent la défense contre les XSS. Il est essentiel de comprendre les principes de base, mais en pratique, vous devriez vous fier à votre bibliothèque de modèles pour 99 % de la protection contre les XSS.
Lorsque vous écrivez des modèles qui sont rendus au balisage ou au code exécuté dans un navigateur, la clé de la protection contre les XSS est le *encodage*. Dans ce contexte, le codage consiste à prendre une séquence de caractères et à la transformer en un format qui sera traité d'une manière spécifique par l'interpréteur.
Mais le type d'encodage à utiliser dépend de l'endroit ou du contexte dans lequel les données seront utilisées.
- Inside a tag, like `<div>User input here</div>`: **HTML Encoding**
- Inside an attribute, like `<input placeholder="User input here"></input>`: **Attribute Encoding**
- Inside Javascript, like `<script>x = "User input here";</script>`: **JavaScript Encoding**
Certains cadres renonceront à l'encodage comme principal moyen de défense et utiliseront plutôt l'assainissement pour débarrasser une valeur de tout contenu susceptible d'être dangereux. Il s'agit d'un processus beaucoup plus complexe, avec de nombreux cas de figure à prendre en compte. Il n'est pas recommandé d'implémenter vos propres routines d'assainissement.
Exemples
Examinons quelques exemples dans différentes langues pour voir à quoi cela ressemble en action.
C# - Insecure : Razor
Si un objet `ItmlContent` est préfixé par un `@`, la valeur est directement placée dans le modèle sans aucun encodage.
<!--- UNSAFE: The htmlSnippet will get interpreted without any escaping --->
@Html.Raw(htmlSnippet)
C# - Sécurisé : Razor
Par défaut, toute `chaîne` préfixée par un `@` est échappée HTML dans les modèles Razor.
<!--- SAFE: The htmlSnippet will get HTML escaped --->
@htmlSnippet
Java - Sécurisé : JSP
Lorsque vous utilisez `c:out`, le XML escape est utilisé par défaut (ce qui peut être modifié avec la propriété `escapeXml`), ce qui protège contre les XSS dans un contexte HTML, mais pas dans d'autres contextes.
<div><c:out value="<%= author %>" /></div>
Java - Sécurisé : (fnxml)
Comme ci-dessus, vous pouvez aussi appeler directement `fn:escapeXml`, qui échappera au XML l'entrée qui lui est donnée. Ceci ne protège que dans un contexte HTML.
<div>${fn:escapeXml(author)}</div>
Javascript - Insecure : Angular innerHtml
En spécifiant la propriété `innerHTML`, comme son nom l'indique, vous serez exposé au risque de XSS dû à la désactivation de l'encodage de sortie.
<!--- UNSAFE: The htmlSnippet will get interpreted without any encoding --->
<p [innerHTML]="htmlSnippet"></p>
Javascript - Sécurisé : Angular interpolé
L'interpolation de texte par Angular à l'aide d'accolades doubles (`{{` et `}}`) échappe HTML en sortie, ce qui protège contre le XSS.
<!--- SAFE: The htmlSnippet will get encoded and then interpreted --->
<p>{{htmlSnippet}}</p>
Javascript - Insécurisé : React dangereuxInnerHtml
En spécifiant la propriété `dangerouslySetInnerHTML`, comme son nom l'indique, vous serez exposé au risque de XSS dû à la désactivation de l'encodage de sortie.
<!--- UNSAFE: As the name suggests, the dangerouslySetInnerHTML attribute is dangerous as it does not escape the output --->
<div dangerouslySetInnerHTML={{ __html: htmlSnippet }} />;
Javascript - Sécurisé : React interpolé
L'interpolation de texte par React à l'aide d'accolades (`{` et `}`) échappe HTML en sortie, ce qui protège contre le XSS.
<!--- SAFE: The htmlSnippet will get encoded and then interpreted --->
<div>{htmlSnippet}</div>
Python - Insecure : Django
Si vous utilisez le filtre `safe` dans un modèle Django, il désactivera l'échappement automatique de la sortie, et ne protégera donc pas contre les XSS.
<!--- UNSAFE: The htmlSnippet will not get HTML encoded --->
<div>{{ htmlSnippet | safe }}</div>
Python - Sécurisé : Django
L'interpolation de texte par Django à l'aide d'accolades doubles (`{{` et `}}`) échappe HTML en sortie, ce qui protège contre les XSS.
<!--- SAFE: The htmlSnippet will HTML encoded --->
<div>{{ name }}</div>