Se protéger des failles XSS avec les headers CSP (Content Security Policy)
Les failles XSS (Cross-Site Scripting), étant classées en troisième position du dernier TOP 10 de l’OWASP, sont une porte d’entrée dans les systèmes d’information (scan de ports, exploits, etc.) et une menace pour les utilisateurs (vol d’information d’identifications). Les traditionnelles contre mesures mises en place sont le filtrage des données entrantes sur le serveur (input filtering) et l’encodage des données sortantes (output encoding) afin d’éviter l’exécution de scripts malveillants sur les postes clients.
Principe
Une autre manière de se protéger de ce type de faille est de mettre en place le header HTTP Content-Security-Policy définissant la stratégie mise en place pour contrôler les contenus récupérés et envoyés par une page web côté client. Le principe du CSP est de définir quelles sources pourront être utilisées pour les scripts javascript, les styles CSS, les fonts, les POST de formulaires, les requêtes AJAX, etc.
Les sources disponibles sont les suivantes :
- self : domaine courant
- none : aucun domaine
- all : tous les domaines
- liste de domaines séparés par un espace.
Si un élément n’a pas de configuration, la valeur du paramètre default-src sera utilisée.
default-src dispose de 2 valeurs supplémentaires disponibles :
- unsafe-inline : autorise l’exécution de scripts inline (
<script></script>
). Avec CSP ils sont par défaut interdits - unsafe-eval : autorise l’utilisation de la méthode
eval()
En plus des types de ressources énumérés ci-dessus, d’autres options sont disponibles, entre autres :
- Manipulation du module Anti-XSS des navigateurs
- Gestion de nonce pour les scripts inline (CSP v2)
Récupération de contenu
La quasi totalité des éléments (font, fichiers de style CSS, fichiers javascript, images, iframe, etc.) pouvant être téléchargés et/ou exécutés par une page web peuvent être contrôlés par CSP. Pour chacun de ces éléments il est possible de définir une ou plusieurs sources de confiance.
Par exemple :
- Javascript et CSS : tous les fichiers doivent provenir du domaine suivant : https://cdn.azure.com
- Images : toutes les images doivent provenir du domaine : http://images.azure.com
- Les scripts inline (
<script></script>
) sont interdits - Pour tous les autres contenus, n’autoriser que le domaine de la page courante
Se traduira par le header HTTP suivant :
Content-Security-Policy: default-src 'self' ; script-src https://cdn.azure.com; style-src https://cdn.azure.com; img-src http://images.azure.com;
La liste des paramètres est disponible ici.
Envoi de contenu
De la même manière, il est possible de définir une politique pour l’émission de requêtes depuis la page cliente. C’est principalement le cas pour les requêtes AJAX et les formulaires (CSP v2).
Par exemple :
- Requêtes AJAX/WebSocket : N’autoriser les requêtes que vers les domaines : https://api.monsite.com et https://api.sitetiers.com
- Envoi de formulaire : N’autoriser les requêtes que vers le domaine courant
Se traduira par le header HTTP suivant :
Content-Security-Policy: connect-src https://api.sitetiers.com https://api.monsite.com; form-action 'self' ;
Les paramètres sont cumulables avec l’exemple précédent.
Mode reporting
Mettre en place CSP avec une mauvaise configuration peut avoir de lourdes conséquences sur un site web. Si une source est oubliée, on peut facilement se retrouver avec des fichiers javascript qui ne se chargent pas, un site sans style CSS ou sans images par exemple.
A des fins de tests, le header Content-Security-Policy-Report est disponible. Il se comporte comme le header Content-Security-Policy mais ne bloque pas réellement les ressources.
Exemple :
CSP met également à disposition un paramètre report-uri pour notifier une url des violations de stratégies CSP via une requête POST.
Exemple de requête report reçue :
Compatibilité et versions
En terme de compatibilité, la version 1 de ce header est pris en charge par les dernières versions de principaux navigateurs :
Source : http://caniuse.com/#feat=contentsecuritypolicy
La version 2 n’est quant à elle pas encore disponible partout :
Source : http://caniuse.com/#feat=contentsecuritypolicy2
Sur les navigateurs non compatibles, le header est simplement ignoré.
Un draft de la version 3 est sorti et est disponible ici.
Implémentation
Pour implémenter le CSP sur un site web, il suffit de rajouter des headers HTTP personnalisés sur les réponses faites par notre serveur. Ce type de mécanisme est intégré à la plupart des frameworks de développement web.
Afin de faciliter la mise en place et la maintenabilité des règles CSP, certaines librairies sont disponibles en fonction des frameworks. Par exemple :
Le serveur web peut également être configuré pour ajouter automatiquement ce header HTTP à toutes les requêtes sortantes.
Liens utiles
- Documentation : http://content-security-policy.com/
- Générateur : https://report-uri.io/home/generate
- CheatSheet : https://scotthelme.co.uk/csp-cheat-sheet/
- Article sur le blog de GitHub : http://githubengineering.com/githubs-csp-journey/
- Articles sur le blog de DropBox : * https://blogs.dropbox.com/tech/2015/09/on-csp-reporting-and-filtering/ * https://blogs.dropbox.com/tech/2015/09/unsafe-inline-and-nonce-deployment/ * https://blogs.dropbox.com/tech/2015/09/csp-the-unexpected-eval/ https://blogs.dropbox.com/tech/2015/09/csp-third-party-integrations-and-privilege-separation/