Le Cross Site Scripting - XSS
Définition
L'attaque XSS (pour Cross Site Scripting) est une attaque très populaire presque au même titre que l'injection SQL. Elle est également présente dans le podium (à dix marches) d'OWASP en 2017.
L'attaque XSS vise comme cible le client plutôt que le serveur. Elle se sert d'un script
Javascript qui sera exécuté chez le client pour détourner le fonctionnement de son navigateur. En effet, le pirate développe un script Javascript selon ses attentions, il soumet ensuite ce script comme étant une chaine de caractères à un serveur via une de ses entrées (formulaire, URL...). Si le serveur présente une vulnérabilité vis-à-vis du XSS, alors le script sera accepté et probablement déposé dans la base de données (ou autre forme de source de données). Jusqu'ici il ne se passe rien de spécial. Mais imaginez qu'à un certain moment un client se connecte sur le serveur et demande une page qui affiche les entrées de la base de données, et par hasard c'est le contenu Javascript qui sera envoyé au navigateur. Puisque Javascript est un langage coté client, alors il sera aussitôt exécuté sur le navigateur du client et fera ce qui a été demandé par le pirate.
Dans ce cas de figure, n'importe quel client peut être victime de cette attaque. Tout dépend de qui a demandé l'affichage du contenu de la base de données qui coïncide avec le script. Par contre, si le pirate veut viser un client en particulier alors il peut lui envoyer un message privée encapsulant une attaque XSS via un site Web (présentant la vulnérabilité) comme un forum de discussion ou autre.
Une attaque XSS peut également provoquer des dommages parfois conséquents comme par exemple:
- Rediriger un utilisateur à son insu vers un site pirate ou site compromettant
- Afficher des messages indésirables sur le navigateurs du client
- Empêcher l'exécution normale des scripts embarqués dans la page
- Ordonner le déclenchement de périphériques sur l'ordinateur de la victime comme la Webcam
Il y a quelques années, les pirates pouvaient même voler les cookies de la victime à l'aide de l'attaque XSS et usurper ainsi son identité. Heureusement, une telle action n'est plus possible.
Exploitation
Comme le principe est de poser un script javascript sur le serveur et attendre à ce qu'un client le charge et l'exécute à son insu, alors le pirate commence par écrire un bout de code javascript.
Exemple:
<script>
window.location="http://www.site_dangereux_et_compromettant.com";
</script>
Ensuite, le pirate dépose ce code sur une des entrées d'un site Web (qui est supposé contenir la vulnérabilité) puis poste le tout. Désormais le code est présent sur la base de données et ne fait rien.
Il suffit maintenant qu'un client (la victime) se connecte au site et demande l'affichage des entrées (ou quelques unes) de la base de données. Si le script fait partie des entrées demandées, le navigateur du client sera immédiatement redirigé vers le site pirate.
Variantes du XXS: Reflected XSS et Stored XSS
Le
Reflected XSS est une variante de la vulnérabilité XSS qui survient au moment de l'injection d'un code malveillant via les entrées de l'application Web et qui donne lieu à l'exécution de ce code-là au moment même sur le navigateur. Cette variante d'XSS n'est pas très dangereuse car elle s'exécute sur le navigateur du pirate lui-même et ne risque pas de s'exécuter sur le navigateur d'une personne tierce.
Le
Stored XSS par contre est plus dangereuse, car le pirate injecte le code malveillant dans l'application Web et celle-ci le stocke en dur (dans une base de données par exemple). Ce code-là attend le moment qu'il soit chargé par une victime puis s'exécute sur le navigateur de celle-ci.
Comment s'en protéger?
Les mesures de sécurité que nous allons voir seront implémentés au niveau du serveur et non pas sur le client. Donc, si le serveur est sécurisé contre les attaques XSS, ses clients n'auront pas à affronter des ennuis comme ce qui a été expliqué dans le paragraphe précédent.
Au niveau du code PHP
Comme pour les injections SQL, l'attaque XSS est dues à des entrées provenant de l'extérieur (donc non fiables). La solution consiste donc à filtrer les entrées de l'utilisateur en appliquant les fonctions comme
addslashes() ou
strip_tags() qui supprime toutes les balises contenues dans la chaine entrée. On peut aussi formater les mots-clés HTML à l'aide de la fonction
htmlentities() ou
htmlspecialchars(). Cependant, une chaine de caractères faisant office d'un script XSS est généralement longue, il faut alors n'autoriser qu'une certaine longueur maximale pour les entrées en la vérifiant à l'aide de la fonction
strlen() ou en la tronquant systématiquement à l'aide la fonction
substr().
Au niveau de la configuration du serveur
Comme pour l'injection SQL, on peut activer la directive
magic_quotes_gpc dans le fichier
php.ini pour échapper automatiquement tous les caractères spéciaux (notamment les simples et doubles quotes) figurants dans les chaines provenant le l'extérieur. Bien que ce n'est pas suffisant, mais cette solution apportera un peu d'aide quand même.
magic_quotes_gpc = On
Appliquer le mécanisme Content Security Policy (CSP)
Content Security Policy (ou CSP) est un mécanisme standard de sécurité du contenu intégré aux applications Web. L'implémentation de ce mécanisme permet de réduire, voire éliminer certains types d'attaques ciblant les pages Web, en l'occurrence le XSS.
L’implémentation du CSP pour mitiger les tentatives du XSS peut s'appliquer dans plusieurs niveaux:
Au niveau du code PHP:
header("X-XSS-Protection: 1; mode=block");
Au niveau de la configuration du serveur (Fichier principal du serveur Apache ou fichier .htaccess):
Header set X-XSS-Protection "1; mode=block"
Dans le serveur Nginx la directive devient:
add_header "X-XSS-Protection" "1; mode=block";
Afin que les headers personnalisés soient envoyés par le serveur Apache il faut activer le module headers comme ceci: a2enmod headers.
Pour d'amples informations sur le mécanisme Content Security Policy, je vous renvoie vers cet
article sur MDN Web Docs.