Content Security Policy : plus de sécurité pour le contenu Web

Le contenu actif sur les sites Web, par exemple JavaScript, CSS et ActiveX, représente un risque de sécurité pour les internautes et les exploitants de sites Web. En effet, ces contenus peuvent être touchés par le Cross-Site scripting. C’est pourquoi, la Content Security Policy (CSP) ou politique de sécurité du contenu, a été introduite afin de s’assurer que les pages Internet puissent être utilisées sans doute et hésitation. Le standard de sécurité est conçu pour se protéger contre les attaques malveillantes et est désormais pris en charge par la plupart des navigateurs Web. Le mécanisme de sécurité protège à la fois les sites Web et les internautes. Mais qu’est-ce qui se cache derrière la CSP et comment fonctionne-il ?

Développement de la Content Security Policy

Content Security Policy remonte à 2004, à l’époque connu encore sous le nom de « Content-Restriction ». Sa création s’explique par les lacunes croissantes en termes de sécurité des scripts Internet. Le Cross-Site scripting (XSS), une méthode criminelle d’infiltration de code dans un site Web, représente un risque particulier pour les internautes. Même si les utilisateurs appellent un site Web qui est digne de confiance, un script s’y exécute et charge des données malveillantes à partir d’une source externe. Les cybercriminels utilisent les vulnérabilités pour commenter les fonctions du site Web par exemple. De cette façon, ils peuvent accéder à des ordinateurs personnels sans même que les internautes en soient conscients. La plupart des Webmasters ne remarquent pas non plus qu’un code étranger a été inséré.

Pour résoudre ce problème, la Fondation Mozilla a été à l’initiative du développement de CSP. L’avantage de ce mécanisme de sécurité est que des règles peuvent être définies dans le navigateur : les scripts que le logiciel est autorisé à modifier et ceux qui ne le sont pas. Pour cela, la Content Security Policy utilise des en-têtes HTTP.

Remarque

la fondation Mozilla est l’organisation derrière le développement du navigateur Firefox. L’organisme à but non lucratif est responsable de la direction des projets et des innovations de Mozilla sur Internet. La fondation a été fondée par d’anciens employés de Netscape qui avaient développé alors l’un des premiers navigateurs Web.

Comment fonctionne la Content Security Policy ?

Lors de la communication sur Internet, le client et le serveur échangent des données via le protocole HTTP (Hypertext Transfer Protocol). Les champs d’en-tête HTTP sont une partie importante des requêtes et des réponses : les paramètres et arguments importants pour l’échange des deux interlocuteurs (serveur et client) sont transmis dans ces derniers. Ils sont généralement divisés en champs de requête et de réponse et peuvent contenir des informations sur le jeu de caractères, la langue et les cookies, par exemple. CSP est implémenté comme un champ d’en-tête de réponse.

L’en-tête Content Security Policy est créé par le Webmaster et inséré sur chaque sous-page du site Web sur laquelle le mécanisme de sécurité doit s’appliquer. En tant qu’exploitant du site Web, vous avez la possibilité de définir différentes précautions de sécurité pour chaque page individuelle. Vous pouvez mettre en œuvre le concept de sécurité plus facilement en créant des fichiers .htaccess dans les mêmes dossiers (ou hiérarchiquement supérieurs) que les pages Web correspondantes, ou en ancrant CSP directement dans la configuration du serveur.

Note

si, en tant qu’internaute, vous souhaitez vérifier que votre navigateur prend en charge Content Security Policy, vous pouvez exécuter le CSP Browser Test. Il essaie de charger des scripts et des images provenant de sources externes (inoffensives) et vous indique si cela a réussi. Votre navigateur est sûr s’il ne charge pas les sources externes, c’est à dire qu’il comprend et utilise le CSP.

Dans le sens de la Content Security Policy et pour éviter le Cross-Site scripting, les responsables Web devraient stocker tous les scripts dans des fichiers séparés au lieu de les intégrer directement dans le code source de la page d’accueil. Le CSP fonctionne alors selon le principe de la liste blanche (Whitelist) : l’en-tête énumère les sources à partir desquelles les scripts et les données peuvent être chargés. Si un script externe a été inséré dans le code HTML de la page sans être reconnu et essaie maintenant de charger des données externes, le navigateur de l’utilisateur doit alors l’interdire. Par défaut, un CSP bloque tous les scripts qui sont directement dans le code (scripts en ligne). Cela protège à la fois le site Web et l’internaute et surtout leurs données sensibles.

Les manipulations par le biais du Cross-Site scripting sont relativement faciles pour les cybercriminels. Presque toutes les pages du Web ont un champ de saisie : par exemple la fonction de commentaire, la barre de recherche ou encore le champ de connexion. Au lieu d’un simple texte, des scripts peuvent aussi y être insérés. Si le serveur n’est pas correctement sécurisé, les criminels mettent en places de cette façon des interfaces d’hameçonnage et immobilisent l’ensemble du site Web ou prennent le contrôle du navigateur Web de l’utilisateur par le biais d’un logiciel malveillant. La CSP (ou plus exactement le champ d’en-tête correspondant) indique au navigateur Web à partir de quelles sources il peut charger des données. Si la « Politique » est implémentée dans le code du site Web, la tentative de récupération du code introduit via XSS est suivie d’un message d’erreur. En utilisant la Content Security Policy, les Webmasters peuvent aussi effectuer de nombreux autres réglages, par exemple par le biais de ces directives :

  • base-uri : limite les URL qui peuvent apparaître dans l’élément <base> de la page Web.
  • child-src : détermine à partir de quelles sources, les données peuvent apparaître dans les trames, par exemple pour les vidéos embarquées de fournisseurs tiers.
  • connect-src : limite les sources avec lesquelles la page peut se connecter, par exemple via des liens.
  • font-src : détermine les sources à partir desquelles les polices peuvent être chargées.
  • form-action : apporte une liste de critères d’évaluation valides dans les formulaires.
  • frame-ancestors : détermine quels domaines peuvent inclure la page dans les Frames et iFrames.
  • img-src : limite les sources à partir desquelles les images peuvent être chargées.
  • media-src : spécifie à partir de quelles sources les formats audio et vidéo peuvent être chargés.
  • object-src : définit le contrôle de Flash et d’autres plugins.
  • plugin-types : limite les types de plugins
  • report-uri : spécifie une URL à laquelle les rapports sont envoyés si les mesures de sécurité ont été violées.
  • script-src : détermine quelles sources sont autorisées pour JavaScript
  • style-src : fonctionne comme script-src, mais est utilisé pour les feuilles de style.
  • upgrade-insecure-requests : définit que les pages non sécurisées sont traitées comme des pages HTTPS avec HTTP.
  • Sandbox : déplace la page dans un Sandbox ou les formulaires, pop-ups, scripts, etc. sont interdits.

Ces directives ne sont valables que si elles sont explicitement définies. Dans le cas contraire, elles sont ouvertes par défaut et représentent donc une faille de sécurité. Cependant, ceci peut être ici changé avec default-src : vous pouvez définir l’état par défaut de toutes les directives se terminant par –src. Par exemple, au lieu de la laisser ouverte, vous définissez que seules les données de votre propre site Web peuvent être chargées, à moins que vous n’ayez alors spécifié le contraire dans l’en-tête HTTP d’une page Web individuelle. Ajoutez ensuite d’autres sources dans les directives séparées.

Vous pouvez saisir un nombre quelconque de directives dans la zone d’en-tête. Si vous voulez inclure plusieurs directives, séparez-les par des points virgules. De plus, en tant que Webmaster, vous devez spécifier toutes les sources dans une directive. Les citations multiples des mêmes directives avec des sources supplémentaires comme dans l’exemple suivant ne sont pas autorisées :

script-src exemple1.local; script-src exemple2.local

Dans ce cas, seule la première source est pertinente, la seconde serait ignorée par le client. Vous devez plutôt noter les deux sources dans une directive :

script-src exemple1.local exemple2.local

Si vous n’avez pas besoin de certains types de contenu pour une page ou pour l’ensemble du site Internet, vous pouvez alors entrer la valeur 'none'  dans l’en-tête des directives correspondantes, vous spécifiez ainsi qu’aucune source ne peut être chargée du tout. Vous pouvez aussi utiliser la valeur 'self' pour spécifier que le navigateur ne peut charger que du contenu provenant de la même source. Les deux valeurs doivent toujours être écrites entre guillemets simples, sinon none et self seront interprétés comme des domaines.

Il existe différentes options d’en-tête pour définir une Content Security Policy :

  • Content Security Policy
  • X-Webkit CSP
  • X-Content Security Policy

Tous les navigateurs ne supportent pas tous les noms. Cependant, le W3C (l’organisme de standardisation sur le Web) propose une Content-Security-Policy. Par conséquent, tous les navigateurs modernes se sont adaptés à ce standard de sécurité (les deux autres versions sont considérés comme obsolètes). Pour vous assurer d’atteindre le plus grand nombre possible d’internautes (même ceux dont la version du navigateur est dépassée) avec votre CSP, il est recommandé d’inclure tous les champs d’en-tête. Si un navigateur Web ne peut pas utiliser l’en-tête Content Security Policy, il l’ignorera simplement et affichera le site Web sans problème, cependant, la protection supplémentaire n’est pas fournie aux utilisateurs concernés.

Vous définissez habituellement les en-têtes HTTP à travers les pages pour l’ensemble de votre domaine. Pour les sous-répertoires, vous pouvez utiliser le fichier .htaccess. Vous utilisez ensuite le mécanisme de sécurité CSP pour définir des règles spéciales pour des sous-pages individuelles.  Par exemple, si vous avez implémenté un bouton de médias sociaux sur une page mais pas sur la suivante, il est logique de n’autoriser l’accès qu’à la source externe sur la première page.

Les sources peuvent être saisies sous forme d’adresses, à leurs façons ou sous forme de Wildcard (Joker). Les entrées suivantes sont donc autorisées :

  • script-src 'https://example.com:443' – Les scripts ne sont autorisés à partir de ce domaine que via HTTPS.
  • script-src 'none' – Les scripts ne doivent pas être chargés.
  • script-src 'self' – Les scripts peuvent être chargés depuis la même source que la page principale, mais pas depuis les sous-domaines.
  • script-src https: – Les scripts peuvent être chargés à partir de n’importe quel domaine tant qu’il débute par HTTPS.
  • script-src example.com – Les scripts peuvent être chargés à partir de ce domaine
  • script-src *.example.com – Les scripts de ce domaine et de tous les sous-domaines sont autorisés.
  • img-src data: – Les images peuvent être chargées via des URL de données

Une Content Security Policy stipule fondamentalement que les scripts ne peuvent être chargés qu’à partir de fichiers, et non directement à partir du code du site Web. Si vous voulez éviter cela, vous pouvez utiliser la commande script-src 'unsafe-inline'. Cependant, vous devez être conscient que cela crée à son tour une faille de sécurité. La norme de sécurité interdit aussi la fonction eval (). En fait, vous pouvez convertir le texte en code JavaScript avec cette commande, mais même ceci est un risque de sécurité. Si vous avez encore besoin de cette fonction, vous pouvez la réactiver avec script-src 'unsafe-eval'.

Conseil

vous pouvez sécuriser unsafe-inline avec un détour. Les valeurs de hachage ou la source Nonce comblent cette faille de sécurité.

Si les scripts ne sont plus autorisés à apparaître directement dans le code, vous devez créer un fichier séparé pour chaque script. La fonction du script est stockée dans un fichier .js. Seulement s’ils sont référencés dans le code du site Web :

<script src='beispiel.js'></script>

Ce que le script fait au final est décrit dans exemple.js. Vous devez aussi stocker les éléments de style dans des feuilles de sytle séparées. Si, en tant que Webmaster, vous souhaitez introduire un Content Security Policy, il ne suffit pas d‘insérer l’en-tête. Vous devez aussi vérifier et adapter le code source de votre site Web.

Note

vous voulez savoir dans quelle mesure votre propre site Web est sécurisé ? Mozilla apporte un test facile à utiliser : Observatory by Mozilla qui vous donne un score après un scan et vous indique où et comment rendre votre site plus sûr.

Content Security Policy : un exemple

À l’aide d’un exemple, nous allons maintenant vous montrer comment réaliser un en-tête Content Security Policy et expliquer ce qui doit être fait avec l’en-tête.

  • Content-Security-Policy: "default-src 'none'; script-src 'self' *.example.com; style-src 'self'; img-src 'self' data:; font-src 'self' https://fonts.google.com/; report-uri 'https://example.org/report.html';
  • X-Content-Security-Policy: "default-src 'none'; script-src 'self' *.example.com; style-src 'self'; img-src 'self' data:; font-src 'self' https://fonts.google.com/; report-uri 'https://example.org/report.html';
  • X-WebKit-CSP: "default-src 'none'; script-src 'self' *.example.com; style-src 'self'; img-src 'self' data:; font-src 'self' https://fonts.google.com/; report-uri 'https://example.org';

Vous verrez que chaque variante de la CSP apparait dans l’en-tête pour que le plus de navigateurs puissent être adressés. Dans chaque en-tête, le contenu est identique : les sources sont listées l’une après l’autre et les directives sont séparées par un point-virgule. La syntaxe est toujours la même. En fait, seul le nom du champ change, de sorte que vous pouvez simplement dupliquer le contenu.

Tout d’abord, nous spécifions que, sauf indication contraire dans une directive, les données ne doivent pas être chargées à partir d’une source quelconque (default-src). Cela comble une lacune en matière de sécurité. Vous devez toujours définir default-src en premier. Cela permet d’éviter qu’une directive oubliée ne laisse une lacune dans votre Content Security Policy.

Ensuite, nous définissions la source à partir de laquelle les scripts peuvent être chargés (script-src). Dans l’exemple, nous spécifions que le navigateur ne charge que les scripts provenant de la même source et de example.com avec tous les sous-domaines (vous attribuez le Joker avec *). De plus, nous spécifions que les clients ne peuvent charger des feuilles de style qu’à partir de leur propre source (style-src). Les images ne sont autorisées qu’à partir de leur propre source en tant qu’URL de données (img-src). Selon l’en-tête Content-Security-Policy, les polices ne peuvent être chargées qu‘à partir d’une source et de l’offre de Google. Enfin, dans l’exemple, nous spécifions un endroit où les messages sont envoyés si quelqu’un tente de violer les normes de sécurité (report-uri).

Vous remarquerez que nous n’avons pas inclus toutes les directives dans l’en-tête. Ce n’est pas du tout un problème : dans le cas présent, nous n’avons pas besoin d’autres listes blanches, et avec default-src, toutes les autres sources sont désactivées.

Conseil

plusieurs générateurs de Content-Security-Policy sont disponibles sur Internet. Avec des offres comme CSP Is Awesome ou Report URI, vous pouvez créer des champs d’en-tête CSP facilement et de manière fiable.