Content Security Policy

Joe Medley
Joe Medley

Le modèle de sécurité du Web repose sur le règlement de même origine. Le code provenant de https://mybank.com ne doit avoir accès qu'aux données de https://mybank.com, et l'accès ne doit jamais être accordé à https://evil.example.com. Chaque origine est isolée du reste du Web, offrant ainsi aux développeurs un bac à sable sécurisé pour créer et jouer. En théorie, c'est tout à fait génial. En pratique, les pirates informatiques ont trouvé des moyens astucieux de renverser le système.

Les attaques par script intersites (XSS), par exemple, contournent la même règle d'origine en incitant un site à diffuser du code malveillant avec le contenu souhaité. Il s'agit d'un problème majeur, car les navigateurs considèrent que tout le code qui s'affiche sur une page fait partie intégrante de la sécurité de cette page. L'aide-mémoire XSS est un exemple ancien mais représentatif des méthodes qu'un pirate informatique pourrait utiliser pour violer cette confiance en injectant du code malveillant. Si un pirate informatique injecte n'importe quel code, la partie est presque terminée: les données de session utilisateur sont compromises et les informations qui doivent être tenues secrètes sont exfiltrées vers The Bad Guys. Nous essaierons évidemment de les éviter si possible.

Cette présentation met en évidence une défense qui peut réduire considérablement le risque et l'impact des attaques XSS dans les navigateurs modernes: Content Security Policy (CSP).

Résumé

  • Utilisez des listes d'autorisation pour indiquer au client ce qui est autorisé et ce qui ne l'est pas.
  • Découvrez les directives disponibles.
  • Identifiez les mots clés qu'ils utilisent.
  • Le code intégré et les eval() sont considérés comme dangereux.
  • Signalez les cas de non-respect des règles à votre serveur avant de les appliquer.

Listes d'autorisation sources

Le problème exploité par les attaques XSS est l'incapacité du navigateur à faire la distinction entre le script qui fait partie de votre application et le script injecté de manière malveillante par un tiers. Par exemple, le bouton +1 de Google en bas de cette page charge et exécute le code de https://apis.google.com/js/plusone.js dans le contexte de l'origine de cette page. Nous faisons confiance à ce code, mais nous ne pouvons pas nous attendre à ce que le navigateur détermine par lui-même que le code provenant de apis.google.com est génial, contrairement à celui provenant de apis.evil.example.com. Le navigateur télécharge et exécute avec plaisir tout le code demandé par une page, quelle que soit la source.

Au lieu de faire aveuglément confiance à tout ce qu'un serveur fournit, CSP définit l'en-tête HTTP Content-Security-Policy, qui vous permet de créer une liste d'autorisation de sources de contenu fiable et demande au navigateur de n'exécuter ou d'afficher que les ressources de ces sources. Même si un pirate informatique parvient à trouver un trou par lequel injecter un script, celui-ci ne correspond pas à la liste d'autorisation et ne sera donc pas exécuté.

Puisque nous faisons confiance à apis.google.com pour fournir du code valide et que nous faisons de même, définissons une stratégie qui n'autorise l'exécution du script que lorsqu'il provient de l'une de ces deux sources:

Content-Security-Policy: script-src 'self' https://apis.google.com

Simple, n'est-ce pas ? Comme vous l'avez probablement deviné, script-src est une instruction qui contrôle un ensemble de droits liés au script pour une page spécifique. Nous avons spécifié 'self' comme source valide de script et https://apis.google.com comme une autre. Le navigateur télécharge et exécute systématiquement JavaScript à partir de apis.google.com via HTTPS, ainsi qu'à partir de l'origine de la page actuelle.

Erreur de la console: chargement du script "http://evil.example.com/evil.js" refusé, car il ne respecte pas la directive Content Security Policy suivante: script-src "self" https://apis.google.com

Lorsque cette règle est définie, le navigateur génère simplement une erreur au lieu de charger le script à partir de toute autre source. Lorsqu'un pirate informatique intelligent parvient à injecter du code dans votre site, il est confronté à un message d'erreur plutôt qu'au succès qu'il s'attendait.

Les règles s'appliquent à une grande variété de ressources

Bien que les ressources de script représentent les risques de sécurité les plus évidents, CSP fournit un ensemble complet d'instructions de stratégie qui permettent un contrôle assez précis sur les ressources qu'une page est autorisée à charger. Vous avez déjà vu script-src. Le concept doit donc être clair.

Examinons rapidement les autres directives de la ressource. La liste ci-dessous représente l'état des directives au niveau 2. Une spécification de niveau 3 a été publiée, mais n'est largement pas implémentée dans les principaux navigateurs.

  • base-uri limite les URL qui peuvent apparaître dans l'élément <base> d'une page.
  • child-src répertorie les URL des nœuds de calcul et du contenu des frames intégrés. Par exemple, child-src https://youtube.com permet d'intégrer des vidéos depuis YouTube, mais pas d'autres origines.
  • connect-src limite les origines auxquelles vous pouvez vous connecter (via XHR, WebSockets et EventSource).
  • font-src spécifie les origines pouvant diffuser les polices Web. Les polices Web de Google peuvent être activées via font-src https://themes.googleusercontent.com.
  • form-action répertorie les points de terminaison valides pour l'envoi à partir de balises <form>.
  • frame-ancestors spécifie les sources pouvant intégrer la page active. Cette directive s'applique aux tags <frame>, <iframe>, <embed> et <applet>. Cette instruction ne peut pas être utilisée dans les tags <meta> et ne s'applique qu'aux ressources non HTML.
  • frame-src est obsolète depuis le niveau 2, mais il est restauré au niveau 3. S'il n'est pas présent, il bascule toujours sur child-src comme précédemment.
  • img-src définit les origines à partir desquelles les images peuvent être chargées.
  • media-src limite les origines autorisées à diffuser des contenus vidéo et audio.
  • object-src permet de contrôler Flash et d'autres plug-ins.
  • plugin-types limite les types de plug-ins qu'une page peut appeler.
  • report-uri spécifie une URL à laquelle le navigateur envoie des rapports en cas de non-respect d'une règle Content Security Policy. Cette instruction ne peut pas être utilisée dans les tags <meta>.
  • style-src est l'équivalent de script-src pour les feuilles de style.
  • upgrade-insecure-requests demande aux user-agents de réécrire les schémas d'URL, en remplaçant HTTP par HTTPS. Cette directive concerne les sites Web comportant un grand nombre d'anciennes URL qui doivent être réécrites.
  • worker-src est une directive CSP de niveau 3 qui limite les URL pouvant être chargées en tant que nœud de calcul, nœud de calcul partagé ou service worker. Depuis juillet 2017, cette directive comporte des implémentations limitées.

Par défaut, les directives sont largement ouvertes. Si vous ne définissez pas de règle spécifique pour une directive, par exemple font-src, cette instruction se comporte par défaut comme si vous aviez spécifié * comme source valide (par exemple, vous pouvez charger des polices à partir de n'importe quel emplacement, sans restriction).

Vous pouvez ignorer ce comportement par défaut en spécifiant une instruction default-src. Cette directive définit les valeurs par défaut pour la plupart des instructions que vous ne spécifiez pas. En règle générale, cela s'applique à toutes les instructions se terminant par -src. Si default-src est défini sur https://example.com et que vous ne spécifiez pas d'instruction font-src, vous pouvez charger des polices à partir de https://example.com et nulle part ailleurs. Nous n'avons spécifié que script-src dans nos exemples précédents, ce qui signifie que les images, les polices, etc. peuvent être chargées à partir de n'importe quelle origine.

Les directives suivantes n'utilisent pas default-src comme solution de remplacement. N'oubliez pas que le fait de ne pas les définir revient à autoriser n'importe quoi.

  • base-uri
  • form-action
  • frame-ancestors
  • plugin-types
  • report-uri
  • sandbox

Vous pouvez utiliser autant d'instructions que nécessaire en fonction de votre application, en les répertoriant toutes dans l'en-tête HTTP, en les séparant par un point-virgule. Veillez à répertorier toutes les ressources requises d'un type spécifique dans une seule directive. Si vous écrivez quelque chose comme script-src https://host1.com; script-src https://host2.com, la deuxième instruction serait simplement ignorée. L'exemple suivant spécifie correctement les deux origines comme valides:

script-src https://host1.com https://host2.com

Si, par exemple, vous disposez d'une application qui charge toutes ses ressources à partir d'un réseau de diffusion de contenu (par exemple, https://cdn.example.net) et que vous savez que vous n'avez pas besoin de contenu encadré ni de plug-ins, votre règle peut se présenter comme suit:

Content-Security-Policy: default-src https://cdn.example.net; child-src 'none'; object-src 'none'

Détails de mise en œuvre

Plusieurs tutoriels sur le Web contiennent les en-têtes X-WebKit-CSP et X-Content-Security-Policy. À l'avenir, vous devez ignorer ces en-têtes préfixés. Les navigateurs récents (à l'exception d'IE) acceptent l'en-tête Content-Security-Policy sans préfixe. C'est l'en-tête que vous devez utiliser.

Quel que soit l'en-tête que vous utilisez, la règle est définie page par page : vous devez envoyer l'en-tête HTTP avec chaque réponse dont vous souhaitez vous assurer qu'elle est protégée. Cela offre beaucoup de flexibilité, car vous pouvez ajuster la règle pour des pages spécifiques en fonction de leurs besoins spécifiques. Il est possible qu'un ensemble de pages de votre site comporte un bouton +1, mais pas d'autres. Vous pouvez autoriser le chargement du code du bouton uniquement lorsque cela est nécessaire.

La liste source de chaque directive est flexible. Vous pouvez spécifier les sources par schéma (data:, https:) ou avec une spécificité allant du nom d'hôte uniquement (example.com, qui correspond à n'importe quelle origine sur cet hôte, quel que soit le schéma ou n'importe quel port) à un URI complet (https://example.com:443, qui correspond uniquement à HTTPS, uniquement à example.com et uniquement au port 443). Les caractères génériques sont acceptés, mais uniquement en tant que schéma, en tant que port ou à la position la plus à gauche du nom d'hôte: *://*.example.com:* correspond à tous les sous-domaines de example.com (mais pas example.com lui-même), à l'aide de n'importe quel schéma, sur n'importe quel port.

La liste source accepte également quatre mots clés:

  • Comme vous pouvez vous y attendre, 'none' ne correspond à rien.
  • 'self' correspond à l'origine actuelle, mais pas à ses sous-domaines.
  • 'unsafe-inline' permet d'intégrer le code JavaScript et CSS. (Nous y reviendrons plus en détail plus tard.)
  • 'unsafe-eval' permet des mécanismes texte-vers-JavaScript tels que eval. (Nous y reviendrons aussi.)

Ces mots clés doivent être entre guillemets simples. Par exemple, script-src 'self' (avec des guillemets) autorise l'exécution de JavaScript à partir de l'hôte actuel. script-src self (sans guillemets) autorise JavaScript à partir d'un serveur nommé "self" (et pas à partir de l'hôte actuel), ce qui n'est probablement pas ce que vous vouliez.

Bac à sable

Voici une autre directive qui mérite d'être évoquée: sandbox. Elle est un peu différente des autres que nous avons examinées, car elle impose des restrictions sur les actions que la page peut effectuer plutôt que sur les ressources qu'elle peut charger. Si l'instruction sandbox est présente, la page est traitée comme si elle avait été chargée dans un élément <iframe> avec un attribut sandbox. Cela peut avoir un large éventail d'effets sur la page: forcer la page à avoir une origine unique et empêcher l'envoi de formulaire, entre autres. Cet article dépasse un peu le cadre de cet article, mais vous trouverez des informations complètes sur les attributs de bac à sable valides dans la section "Bac à sable" de la spécification HTML5.

La balise Meta

Le mécanisme de distribution privilégié des CSP est un en-tête HTTP. Toutefois, il peut être utile de définir une règle sur une page directement dans le balisage. Pour ce faire, utilisez une balise <meta> avec un attribut http-equiv:

<meta
  http-equiv="Content-Security-Policy"
  content="default-src https://cdn.example.net; child-src 'none'; object-src 'none'"
/>

Vous ne pouvez pas l'utiliser pour frame-ancestors, report-uri ni sandbox.

Le code intégré est considéré comme dangereux

Il doit être clair que CSP est basé sur les origines de la liste d'autorisation, car il s'agit d'une manière sans ambiguïté d'indiquer au navigateur de traiter des ensembles spécifiques de ressources comme acceptables et de refuser le reste. Toutefois, les listes d'autorisation basées sur l'origine ne permettent pas de résoudre la plus grande menace posée par les attaques XSS: l'injection de script intégré. Si un pirate informatique peut injecter un tag de script contenant directement une charge utile malveillante (<script>sendMyDataToEvilDotCom();</script>), le navigateur ne dispose d'aucun mécanisme permettant de le distinguer d'un tag de script intégré légitime. CSP résout ce problème en interdisant complètement les scripts intégrés : c'est le seul moyen d'en être sûr.

Cette interdiction concerne non seulement les scripts intégrés directement dans les balises script, mais aussi les gestionnaires d'événements intégrés et les URL javascript:. Vous devez déplacer le contenu des balises script dans un fichier externe, et remplacer les URL javascript: et <a ... onclick="[JAVASCRIPT]"> par les appels addEventListener() appropriés. Par exemple, vous pouvez réécrire ce qui suit à partir de:

<script>
  function doAmazingThings() {
    alert('YOU AM AMAZING!');
  }
</script>
<button onclick="doAmazingThings();">Am I amazing?</button>

par quelque chose comme:

<!-- amazing.html -->
<script src="amazing.js"></script>
<button id="amazing">Am I amazing?</button>

<div style="clear:both;"></div>
// amazing.js
function doAmazingThings() {
  alert('YOU AM AMAZING!');
}
document.addEventListener('DOMContentLoaded', function () {
  document.getElementById('amazing').addEventListener('click', doAmazingThings);
});

Le code réécrit présente un certain nombre d'avantages en plus de fonctionner correctement avec CSP. C'est déjà une bonne pratique, quelle que soit votre utilisation de CSP. Le JavaScript intégré combine la structure et le comportement exactement comme vous ne devriez pas le faire. Les ressources externes sont plus faciles à mettre en cache par les navigateurs, plus compréhensibles pour les développeurs, et favorisent la compilation et la minimisation. Vous rédigerez un meilleur code si vous le déplacez vers des ressources externes.

Le style intégré est traité de la même manière: l'attribut style et les balises style doivent être regroupés dans des feuilles de style externes pour éviter différentes méthodes d'exfiltration de données étonnamment intelligentes activées par le CSS.

Si vous devez disposer d'un script et d'un style intégrés, vous pouvez les activer en ajoutant 'unsafe-inline' en tant que source autorisée dans une instruction script-src ou style-src. Vous pouvez également utiliser un nonce ou un hachage (voir ci-dessous), mais ce n'est absolument pas autorisé. L'exclusion d'un script intégré est la plus grande réussite en termes de sécurité fournie par CSP, et l'interdiction du style intégré renforce également votre application. Il faut un peu d'efforts en amont pour s'assurer que tout fonctionne correctement après avoir déplacé tout le code hors ligne, mais c'est un compromis qui vaut la peine d'être fait.

Si vous devez absolument l'utiliser

CSP de niveau 2 offre une rétrocompatibilité pour les scripts intégrés en vous permettant d'ajouter des scripts intégrés spécifiques à la liste d'autorisation à l'aide d'un nonce cryptographique (un nombre utilisé une fois) ou d'un hachage. Bien que cela puisse être fastidieux, c'est utile au pincement.

Pour utiliser un nonce, attribuez un attribut nonce à votre tag de script. Sa valeur doit correspondre à l'une des sources de confiance. Exemple :

<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
  // Some inline code I can't remove yet, but need to asap.
</script>

Ajoutez maintenant le nonce à votre directive script-src, en plus du mot clé nonce-.

Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'

N'oubliez pas que les nonces doivent être générés à nouveau pour chaque requête de page et doivent être impossibles à deviner.

Les hachages fonctionnent à peu près de la même manière. Au lieu d'ajouter du code au tag de script, créez un hachage SHA du script lui-même et ajoutez-le à la directive script-src. Par exemple, imaginons que votre page contienne les éléments suivants:

<script>
  alert('Hello, world.');
</script>

Votre politique doit contenir les éléments suivants:

Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='

Voici quelques points à noter. Le préfixe sha*- spécifie l'algorithme qui génère le hachage. Dans l'exemple ci-dessus, sha256- est utilisé. CSP accepte également sha384- et sha512-. Lors de la génération du hachage, n'incluez pas les balises <script>. Les majuscules et les espaces sont également importants, y compris les espaces de début ou de fin.

Une recherche Google sur la génération de hachages SHA vous permettra de trouver des solutions dans le nombre de langues que vous souhaitez. À partir de la version 40 de Chrome, vous pouvez ouvrir les outils de développement, puis actualiser votre page. L'onglet "Console" contient des messages d'erreur avec le hachage SHA256 correct pour chacun de vos scripts intégrés.

Évaluer également

Même lorsqu'un pirate informatique ne peut pas injecter directement un script, il peut inciter votre application à convertir un texte inerte en code JavaScript exécutable et l'exécuter en son nom. eval(), new Function(), setTimeout([string], ...) et setInterval([string], ...) sont tous des vecteurs à travers lesquels le texte injecté peut finir par exécuter quelque chose de malveillant de manière inattendue. La réponse par défaut de CSP à ce risque consiste à bloquer complètement tous ces vecteurs.

Cela a plusieurs conséquences sur la façon dont vous créez des applications:

  • Vous devez analyser JSON via l'JSON.parse intégré plutôt que d'utiliser eval. Les opérations JSON natives sont disponibles dans tous les navigateurs depuis IE8 et sont totalement sûres.
  • Réécrivez les appels setTimeout ou setInterval que vous effectuez actuellement avec des fonctions intégrées plutôt que des chaînes. Exemple :
setTimeout("document.querySelector('a').style.display = 'none';", 10);

serait mieux écrit comme suit:

setTimeout(function () {
  document.querySelector('a').style.display = 'none';
}, 10);
  • Évitez les modèles intégrés au moment de l'exécution: de nombreuses bibliothèques de modèles utilisent généreusement new Function() pour accélérer la génération de modèles au moment de l'exécution. Il s'agit d'une application astucieuse de programmation dynamique, qui présente un risque d'évaluation du texte malveillant. Certains frameworks sont directement compatibles avec CSP, en s'appuyant sur un analyseur robuste en l'absence de eval. La directive ng-csp d'AngularJS en est un bon exemple.

Toutefois, un meilleur choix serait un langage de création de modèles qui offre une précompilation (par exemple, Handlebars). La précompilation de vos modèles peut rendre l'expérience utilisateur encore plus rapide que l'implémentation d'exécution la plus rapide, et elle est également plus sûre. Si eval et ses modèles texte-vers-JavaScript sont essentiels pour votre application, vous pouvez les activer en ajoutant 'unsafe-eval' en tant que source autorisée dans une directive script-src, mais nous vous déconseillons vivement de le faire. L'interdiction de l'exécution de chaînes rend beaucoup plus difficile pour un pirate informatique l'exécution de code non autorisé sur votre site.

Fréquence

La capacité de CSP à bloquer les ressources non approuvées côté client est un avantage considérable pour vos utilisateurs, mais il serait très utile de renvoyer une notification au serveur afin de pouvoir identifier et éliminer tout bug autorisant une injection malveillante. À cette fin, vous pouvez demander au navigateur de POST signaler les cas de non-respect au format JSON vers un emplacement spécifié dans une instruction report-uri.

Content-Security-Policy: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;

Ces rapports se présenteront comme suit:

{
  "csp-report": {
    "document-uri": "http://example.org/page.html",
    "referrer": "http://evil.example.com/",
    "blocked-uri": "http://evil.example.com/evil.js",
    "violated-directive": "script-src 'self' https://apis.google.com",
    "original-policy": "script-src 'self' https://apis.google.com; report-uri http://example.org/my_amazing_csp_report_parser"
  }
}

Il contient une bonne partie d'informations qui vous aideront à identifier la cause précise du non-respect, y compris la page concernée (document-uri), l'URL de provenance de cette page (notez que contrairement au champ d'en-tête HTTP, la clé n'est pas mal orthographiée), la ressource qui a enfreint la règle de la page (blocked-uri), l'instruction spécifique enfreinte (violated-directive) et la règle complète de la page (original-policy).

Rapport uniquement

Si vous débutez avec CSP, il est judicieux d'évaluer l'état actuel de votre application avant de déployer une stratégie draconienne pour vos utilisateurs. En guise de tremplin vers un déploiement complet, vous pouvez demander au navigateur de surveiller une règle, en signalant les cas de non-respect, mais sans appliquer les restrictions. Au lieu d'envoyer un en-tête Content-Security-Policy, envoyez un en-tête Content-Security-Policy-Report-Only.

Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;

La règle spécifiée en mode signalement uniquement ne bloque pas les ressources limitées, mais envoie des rapports de non-respect à l'emplacement que vous spécifiez. Vous pouvez même envoyer les deux en-têtes, en appliquant une règle tout en surveillant une autre. C'est un excellent moyen d'évaluer l'effet des modifications apportées à la CSP de votre application: activez la création de rapports pour une nouvelle règle, surveillez les signalements de non-respect et corrigez les bugs éventuels. Lorsque vous êtes satisfait de son effet, commencez à appliquer la nouvelle règle.

Utilisation réelle

CSP 1 fonctionne bien dans Chrome, Safari et Firefox, mais sa compatibilité est très limitée dans IE 10. Vous pouvez consulter les détails sur caniuse.com. CSP de niveau 2 est disponible dans Chrome depuis la version 40. De nombreux sites tels que Twitter et Facebook ont déployé l'en-tête (l'étude de cas de Twitter vaut la peine d'être lue), et la norme est prête à être déployée sur vos propres sites.

Pour élaborer une stratégie pour votre application, la première étape consiste à évaluer les ressources que vous chargez réellement. Une fois que vous pensez maîtriser la façon dont les éléments sont organisés dans votre application, configurez une règle basée sur ces exigences. Examinons quelques cas d'utilisation courants et déterminons comment les gérer au mieux dans les limites de protection de CSP.

Cas d'utilisation n° 1: widgets de réseaux sociaux

  • Le bouton +1 de Google inclut un script de https://apis.google.com et intègre un <iframe> provenant de https://plusone.google.com. Vous avez besoin d'une règle qui inclut ces deux origines pour pouvoir intégrer le bouton. La règle minimale est script-src https://apis.google.com; child-src https://plusone.google.com. Vous devez également vous assurer que l'extrait de code JavaScript fourni par Google est extrait dans un fichier JavaScript externe. Si vous aviez une règle basée sur le niveau 1 utilisant frame-src, le niveau 2 vous obligeait à la remplacer par child-src. Cette opération n'est plus nécessaire au niveau 3 de CSP.

  • Le bouton "J'aime" de Facebook comporte plusieurs options d'implémentation. Nous vous recommandons de vous en tenir à la version de <iframe>, car elle est isolée du reste de votre site dans un bac à sable sécurisé. Elle nécessite une instruction child-src https://facebook.com pour fonctionner correctement. Notez que, par défaut, le code <iframe> fourni par Facebook charge une URL relative, //facebook.com. Modifiez cela pour spécifier explicitement HTTPS : https://facebook.com. Il n'y a aucune raison d'utiliser HTTP si cela n'est pas nécessaire.

  • Le bouton "Tweet" de Twitter repose sur l'accès à un script et à un frame, tous deux hébergés sur https://platform.twitter.com. (Twitter fournit également une URL relative par défaut. Modifiez le code pour spécifier HTTPS lorsque vous le copiez/collez localement). script-src https://platform.twitter.com; child-src https://platform.twitter.com est configuré, tant que vous déplacez l'extrait JavaScript fourni par Twitter dans un fichier JavaScript externe.

  • Les autres plates-formes ont des exigences similaires et peuvent être traitées de la même manière. Nous vous suggérons de définir une default-src sur 'none' et de surveiller votre console pour déterminer les ressources que vous devez activer pour faire fonctionner les widgets.

L'inclusion de plusieurs widgets est simple: il vous suffit de combiner les directives de stratégie, en gardant à l'esprit de fusionner toutes les ressources d'un même type en une seule. Si vous souhaitez les trois widgets de réseaux sociaux, la règle se présente comme suit:

script-src https://apis.google.com https://platform.twitter.com; child-src https://plusone.google.com https://facebook.com https://platform.twitter.com

Cas d'utilisation n° 2: blocage

Supposons un instant que vous gériez un site bancaire et que vous souhaitiez vous assurer que seules les ressources que vous avez écrites peuvent être chargées. Dans ce scénario, commencez avec une règle par défaut qui bloque absolument tout (default-src 'none'), puis créez-la à partir de là.

Supposons que la banque charge toutes les images, tous les styles et tous les scripts à partir d'un CDN à https://cdn.mybank.net, et se connecte via XHR à https://api.mybank.com/ pour extraire différents bits de données. Des cadres sont utilisés, mais uniquement pour les pages locales du site (pas d'origines tierces). Le site ne comporte pas de contenu Flash, aucune police ni aucun élément supplémentaire. L'en-tête CSP le plus restrictif que nous puissions envoyer est le suivant:

Content-Security-Policy: default-src 'none'; script-src https://cdn.mybank.net; style-src https://cdn.mybank.net; img-src https://cdn.mybank.net; connect-src https://api.mybank.com; child-src 'self'

Cas d'utilisation n° 3: SSL uniquement

Un administrateur d'un forum de discussion pour les mariages souhaite s'assurer que toutes les ressources ne sont chargées que via des canaux sécurisés, mais n'écrit pas beaucoup de code. Il ne peut pas réécrire de gros blocs du logiciel de forum tiers rempli de script et de style intégrés. La règle suivante s'applique:

Content-Security-Policy: default-src https:; script-src https: 'unsafe-inline'; style-src https: 'unsafe-inline'

Même si https: est spécifié dans default-src, les directives de script et de style n'héritent pas automatiquement de cette source. Chaque instruction écrase complètement la valeur par défaut pour ce type de ressource spécifique.

L'avenir

Le niveau 2 de la stratégie de sécurité du contenu est une recommandation de candidat. Le groupe de travail du W3C sur la sécurité des applications Web a déjà commencé à travailler sur la prochaine itération de la spécification, le niveau 3 de Content Security Policy.

Si vous êtes intéressé par la discussion sur ces fonctionnalités à venir, passez en revue les archives de la liste de diffusion public-webappsec@ ou rejoignez-nous vous-même.

Commentaires