Une Content Security Policy (CSP) ou politique de sécurité du contenu permet d'améliorer la sécurité des sites web en permettant de détecter et mitiger certains types d'attaques, dont les Cross Site Scripting (XSS) et les injections de contenu. Ces attaques peuvent être utilisées dans divers buts, comme le vol de données, le défacement de site ou la diffusion de malware.

CSP a été conçu pour être parfaitement rétro-compatible (sauf pour la version 2 dans laquelle existent des incompatibilités décrites explicitement comme telles, pour plus d'informations, se référer à la documentation du w3c (en anglais)). Les navigateurs qui ne supportent pas le CSP fonctionnent parfaitement avec les serveurs qui l'implémentent et inversement. Les navigateurs qui ne supportent les directives CSP les ignorent, et fonctionnent comme à leur habitude, en utilisant le standard same-origin policy (politique de même origine) pour les contenus. Dans le cas où un navigateur qui prend en charge CSP visite une page web servie par un serveur qui ne fournit pas de CSP, il va probablement utiliser le standard same-origin policy.

Pour activer CSP, vous devez configurer vos serveurs web pour ajouter aux réponses un en-tête (header) HTTP Content-Security-Policy. Vous pouvez rencontrer des documents qui mentionnent X-Content-Security-Policy comme en-tête, il s'agit d'une version obsolète qu'il n'est plus utile de supporter.

Une autre possibilité consiste à utiliser une balise <meta> pour configurer la politique, par exemple : <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">

Menaces

Mitigation des attaques cross site scripting (XSS)

CSP a pour but premier de bloquer et rapporter les attaques XSS (injections de contenu). Les attaques XSS exploitent la confiance que les navigateurs ont dans le contenu reçu des serveurs. Des scripts malveillants peuvent être exécutés par le navigateur d'une victime parce que le navigateur fait confiance au serveur qui lui envoie des données même quand le contenu ne vient pas de là où il semble venir.

CSP permet aux administrateurs système de réduire ou éliminer les moyens de réaliser des attaques XSS en permettant de spécifier les domaines autorisés à fournir des scripts pour la page visitée. Un navigateur compatible avec la CSP n'exécute que les scripts qui provient d'une origine autorisée par la CSP reçue, en ignorant ceux qui ne sont pas autorisés. On peut ainsi bloquer les domaines non autorisés, les scripts inline (inclus dans une page HTML) ou associés à des événements via les attributs HTML dédiés.

Pour un niveau de protection le plus élevé possible, un site qui voudrait qu'aucun script ne puisse être exécuté peut désactiver tout simplement l'exécution de tout script.

Empêcher les écoutes du trafic

En plus de restreindre les domaines d'où peuvent être chargés des contenus, le serveur peut spécifier quels protocoles peuvent être utilisés, par exemple en forçant l'utilisation de HTTPS pour améliorer la sécurité. Une politique de sécurité complète pour la transmission des données peut non seulement forcer l'utilisation de TLS via HTTPS mais aussi forcer l'utilisation de sécurisés (qui ne peuvent être envoyés qu'en HTTPS) et indiquer de convertir automatiquement toutes les requêtes qui auraient été faites en HTTP simple en requêtes HTTPS. L'utilisation de l'en-tête Strict-Transport-Security to s'assurer que les navigateurs utilisent obligatoirement des connexions chiffrée en TLS (HTTPS).

Utiliser CSP

Configurer une CSP nécessite d'utiliser un en-tête HTTP Content-Security-Policy pour une page web et de spécifier une valeur pour contrôler les ressources que le navigateur est autoriser à charger pour cette page. Ainsi, un page qui charge et affiche des images peut autoriser les images stockées n'importe où mais n'autoriser les envois de formulaires que vers certaines adresses.

Créer votre politique CSP

On peut utiliser l'en-tête HTTP Content-Security-Policy pour définir la politique ainsi :

Content-Security-Policy: politique

La politique est une chaîne de caractères contenant la liste des règles qui constituent la politique CSP.

Écrire une politique

Une politique est définie par une série de règles qui décrivent chacune le comportement attendu pour un certain type de contenu ou pour l'ensemble des requêtes. Un politique peut inclure une règle default-src pour la politique par défaut qui s'applique aux ressources pour lesquelles aucune politique n'est définie. Pour les autres types de politique, on pourra de référer à la page default-src. Pour bloquer les scripts intégrés au code HTML (Javascript inline) et l'utilisation de eval(), une politique doit au moins contenir une directive default-src ou script-src. Pour bloquer les modifications de style intégrés au code HTML (CSS inline avec les attributs HTML <style>) et l'utilisation des balises style, une politique doit au moins contenir une directive default-src ou style-src.

Exemples pour les cas courants

Cette section propose des politiques CSP pour les scenarios les plus classiques.

Exemple 1

Pour un site dont tout le contenu est fourni par le site lui-même (sans inclure les sous-domaines) en HTTPS et qui n'utilise pas le referer des navigateurs :

Content-Security-Policy: default-src 'self'; upgrade-insecure-requests; referrer no-referrer

Exemple 2

Pour un site dont tout le contenu est fourni par le site lui-même ou par les sous-domaines de source-sure.example.net (qui peut être un autre site) :

Content-Security-Policy: default-src 'self' *.source-sure.example.net

Exemple 3

Pour un site dont les images peuvent venir de n'importe où, les musiques et vidéos de toto.local ou tata.local, les scripts par scripts.local :

Content-Security-Policy: default-src 'self'; img-src *; media-src toto.local tata.local; script-src scripts.local

Ici, les contenus doivent par défaut venir de la même origine que la page avec les exceptions précédemment décrites. Cela peut permettre aux utilisateurs d'afficher des images quelconques, mais de ne faire confiance qu'à certains domaines pour les musiques, vidéos et scripts.

Exemple 4

Pour un site dont les données sont au moins privées et pour lequel toutes les données devraient être transmises en HTTPS depuis un domaine précis :

Content-Security-Policy: default-src https://confidentiel.example.net

Cette politique force l'utilisation de HTTPS et exclus tout usage de contenu ne venant pas de https://confidentiel.example.net.

Example 5

Pour un webmail qui permet d'afficher des mails incluant de l'HTML, des images provenant de n'importe où mais pas de Javascript ou autres :

Content-Security-Policy: default-src 'self'; img-src *; child-src: *

Tester une politique

Pour faciliter le déploiement de CSP, on peut le configurer pour seulement reporter les violations de politique sans appliquer réellement la politique. Ainsi, on peut s'assurer que la politique ne bloque pas les usages du site en récupérant les rapports de violation de la politique en test. On peut aussi tester des modifications d'une politique en place via ce même mécanisme.

Pour cela, il suffit d'utiliser l'en-tête Content-Security-Policy-Report-Only, comme cela :

Content-Security-Policy-Report-Only: politique 

Si les en-tête HTTP Content-Security-Policy-Report-Only et Content-Security-Policy sont tous deux présents dans la réponse du serveur, les deux politiques seront respectées, ce qui permet le test d'une nouvelle potique quand il y en a déjà une en place.

Si une politique contient une directive report-uri valide, les navigateurs qui supportent CSP doivent envoyer un rapport pour chaque violation de la politique qu'ils détectent.

Gérer les rapports

Par défaut, les violations de la politique de sécurité ne sont pas rapportés. Pour avoir des rapports de violation, il faut une directive report-uri avec au moins une URL valide à laquelle envoyer les rapports :

Content-Security-Policy: default-src 'self'; report-uri http://reportcollector.example.com/collector.cgi

Il faut également configurer le serveur qui doit recevoir les rapports pour en faire quelque chose d'utile, par exemple les stocker si on veut juste pouvoir les examiner manuellement.

Syntaxe des rapports de violation de politique

Le report contient un objet JSON qui contient :

document-uri
L'URI du document qui pour lequel une violation de la politique est arrivée.
referrer
Le referer de ce document : l'URI du document qui a conduit au document où la violation a eu lieu.
blocked-uri
L'URI de la ressource qui a été bloquée par la politique CSP. Si la ressource vient d'une autre origine que le document principal, alors seuls le protocole, le nom de domaine et le port sont indiqués.
violated-directive
Le nom de la section de la politique qui a été violée.
original-policy
La politique CSP reçue par le client.

Exemple de rapport de violation de politique

Si l'on considère une page http://example.com/connexion.html, qui utilise la politique CSP suivante (qui interdit tout par défaut et autorise les feuilles de style CSS provenant de cdn.example.com) :

Content-Security-Policy: default-src 'none'; style-src cdn.example.com; report-uri /_/csp-reports

et qui contient le code HTML suivant :

<!DOCTYPE html>
<html>
  <head>
    <title>Connectez-vous</title>
    <link rel="stylesheet" href="css/style.css">
  </head>
  <body>
    ... Contenu ...
  </body>
</html>

Dans cette situation, les clients qui visiteraient cette page la verrait avec les styles de base de leur navigateur car les feuilles de style autorisées ne peuvent venir que de cdn.example.com et non du site lui-même (l'origine même de la page) comme <link rel="stylesheet" href="css/style.css"> l'indique au navigateur. En outre, un navigateur (qui supporte CSP) enverrait le rapport de violation de politique CSP suivant à l'adresse http://example.com/_/csp-reports à chaque visite de la page dont il est question :

{
  "csp-report": {
    "document-uri": "http://example.com/connexion.html",
    "referrer": "",
    "blocked-uri": "http://example.com/css/style.css",
    "violated-directive": "style-src cdn.example.com",
    "original-policy": "default-src 'none'; style-src cdn.example.com; report-uri /_/csp-reports"
  }
}

Comme vous pouvez le constater, le rapport inclus l'URI complète de la ressource dans blocked-uri. C'est n'est le cas en général. Ainsi, si la page avait essayé de charger la feuille de style http://anothercdn.example.com/stylesheet.css, le navigateur aurait indiqué seulement "blocked-uri": "http://anothercdn.example.com/", c'est à dire l'origine et non l'URI complète car l'origine de la feuille bloquée est différente de l'origine du site lui-même. La spécification de la CSP, disponible en anglais sur le site du W3C, explique les raisons de ce comportement qui peut surprendre de prime abord. En résumé, ce comportement évite les risques de diffuser des informations confidentielles qui pourraient être incluses dans les URI des ressources provenant d'autres origines.

Compatibilité avec les navigateurs

FonctionnalitéChromeEdgeFirefoxInternet ExplorerOperaSafari
Content-Security-Policy251142321031574
base-uri40 Non35 Non2710
block-all-mixed-content Oui ?48 Non Oui ?
child-src401545 Non2710
connect-src2514236 Non157
default-src251423 Non157
disown-opener Non Non Non Non Non Non
font-src251423 Non157
form-action401536 Non2710
frame-ancestors4015337 Non2610
frame-src251423 Non157
img-src251423 Non157
manifest-src Oui Non41 Non Oui Non
media-src251423 Non157
navigation-to Non Non Non Non Non Non
object-src251423 Non157
plugin-types4015 Non9 Non2710
referrer33 — 56 Non3710 Non Oui — 43 Non
report-sample59 ? ? ?46 ?
report-to Non Non Non Non Non Non
report-uri251423 Non157
require-sri-for54 Non4911 Non41 Non
sandbox25145010157
script-src251423 Non157
strict-dynamic52 Non52 Non39 Non
style-src251423 Non157
upgrade-insecure-requests43 Non1242 Non30 Non
worker-src5913 Non58 Non48 Non
FonctionnalitéAndroid webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
Content-Security-Policy Oui Oui Oui23 ?7.15 Oui
base-uri Oui Oui Non35 ?9.3 Oui
block-all-mixed-content Oui Oui ?48 ? ? Oui
child-src Oui Oui Non45 ?9.3 Oui
connect-src Oui Oui ?23 ?7.1 Oui
default-src Oui Oui ?23 ?7.1 Oui
disown-opener Non Non Non Non Non Non Non
font-src Oui Oui ?23 ?7.1 Oui
form-action Oui Oui Non36 ?9.3 Oui
frame-ancestors ? Oui Non338 ?9.3 Oui
frame-src Oui Oui ?23 ?7.1 Oui
img-src Oui Oui ?23 ?7.1 Oui
manifest-src Oui Oui Non41 ? Non Oui
media-src Oui Oui ?23 ?7.1 Oui
navigation-to Non Non Non Non Non Non Non
object-src Oui Oui ?23 ?7.1 Oui
plugin-types Oui Oui Non Non ?9.3 Oui
referrer33 — 5633 — 56 Non3710 Oui — 43 Non Oui
report-sample5959 ? ?46 ?7.0
report-to Non Non Non Non Non Non Non
report-uri Oui Oui ?23 ?7.1 Oui
require-sri-for5454 Non491141 Non6.0
sandbox Oui Oui ?50 ?7.1 Oui
script-src Oui Oui ?23 ?7.1 Oui
strict-dynamic5252 Non Non39 Non6.0
style-src Oui Oui ?23 ?7.1 Oui
upgrade-insecure-requests4343 Non4230 Non4.0
worker-src59135913 Non5848 Non7.0

1. Implemented as X-Webkit-CSP header in Chrome 14.

2. Implemented as X-Content-Security-Policy header in Firefox 4.

3. Implemented as X-Content-Security-Policy header, only supporting 'sandbox' directive.

4. Implemented as X-Webkit-CSP header in Safari 6.

5. Implemented as X-Webkit-CSP header in iOS 5.1.

6. Prior to Firefox 50, ping attributes of <a> elements weren't covered by connect-src.

7. Before Firefox 58, frame-ancestors is ignored in Content-Security-Policy-Report-Only.

8. Before Firefox for Android 58, frame-ancestors is ignored in Content-Security-Policy-Report-Only.

9. See Bugzilla bug 1045899.

10. Will be removed, see Bugzilla bug 1302449.

11. From version 49: this feature is behind the security.csp.experimentalEnabled preference (needs to be set to true). To change preferences in Firefox, visit about:config.

12. Under consideration for future release.

13. Chrome 59 and higher skips the deprecated child-src directive.

A specific incompatibility exists in some versions of the Safari web browser, whereby if a Content Security Policy header is set, but not a Same Origin header, the browser will block self-hosted content and off-site content, and incorrectly report that this is due to a the Content Security Policy not allowing the content.

Références

Étiquettes et contributeurs liés au document

 Contributeurs à cette page : SphinxKnight, AntoineGrandchamp, David-5-1
 Dernière mise à jour par : SphinxKnight,