Comment fonctionne la politique de sécurité du contenu?


248

Je reçois un tas d'erreurs dans la console du développeur:

Refusé d'évaluer une chaîne

Refus d'exécuter le script en ligne car il viole la directive de politique de sécurité du contenu suivante

Refus de charger le script

Refus de charger la feuille de style

Qu'est-ce que tout cela signifie? Comment fonctionne la politique de sécurité du contenu? Comment utiliser l' Content-Security-Policyen-tête HTTP?

Plus précisément, comment ...

  1. ... autoriser plusieurs sources?
  2. ... utilise des directives différentes?
  3. ... utilise plusieurs directives?
  4. ... gérer les ports?
  5. ... gérer différents protocoles?
  6. ... autoriser le file://protocole?
  7. ... utiliser des styles, des scripts et des balises en ligne <style>et <script>?
  8. ... permettre eval()?

Et enfin:

  1. Que 'self'signifie exactement ?

Réponses:


557

La Content-Security-Policyméta-balise vous permet de réduire le risque d' attaques XSS en vous permettant de définir d'où les ressources peuvent être chargées, empêchant les navigateurs de charger des données à partir d'autres emplacements. Cela rend plus difficile pour un attaquant d'injecter du code malveillant dans votre site.

Je me suis cogné la tête contre un mur de briques en essayant de comprendre pourquoi j'obtenais des erreurs CSP les unes après les autres, et il ne semblait pas y avoir d'instructions concises et claires sur la façon dont cela fonctionne. Voici donc ma tentative d'expliquer brièvement certains points du CSP, en me concentrant principalement sur les choses que j'ai trouvé difficile à résoudre.

Par souci de concision, je n'écrirai pas la balise complète dans chaque échantillon. Au lieu de cela, je ne montrerai que la contentpropriété, donc un exemple qui dit content="default-src 'self'"signifie ceci:

<meta http-equiv="Content-Security-Policy" content="default-src 'self'">

1. Comment autoriser plusieurs sources?

Vous pouvez simplement lister vos sources après une directive en tant que liste séparée par des espaces:

content="default-src 'self' https://example.com/js/"

Notez qu'il n'y a pas de guillemets autour des paramètres autres que les paramètres spéciaux , comme 'self'. De plus, il n'y a pas de deux-points ( :) après la directive. Juste la directive, puis une liste de paramètres séparés par des espaces.

Tout ce qui est en dessous des paramètres spécifiés est implicitement autorisé. Cela signifie que dans l'exemple ci-dessus, ces sources seraient valides:

https://example.com/js/file.js
https://example.com/js/subdir/anotherfile.js

Cependant, ceux-ci ne seraient pas valables:

http://example.com/js/file.js
^^^^ wrong protocol

https://example.com/file.js
                   ^^ above the specified path

2. Comment utiliser différentes directives, que font-elles chacune?

Les directives les plus courantes sont:

  • default-src la politique par défaut pour le chargement de javascript, images, CSS, polices, requêtes AJAX, etc.
  • script-src définit des sources valides pour les fichiers javascript
  • style-src définit des sources valides pour les fichiers css
  • img-src définit des sources valides pour les images
  • connect-srcdéfinit des cibles valides pour XMLHttpRequest (AJAX), WebSockets ou EventSource. Si une tentative de connexion est effectuée avec un hôte non autorisé ici, le navigateur émulera une 400erreur

Il y en a d'autres, mais ce sont ceux dont vous avez le plus besoin.

3. Comment utiliser plusieurs directives?

Vous définissez toutes vos directives à l'intérieur d'une méta-balise en les terminant par un point-virgule ( ;):

content="default-src 'self' https://example.com/js/; style-src 'self'"

4. Comment gérer les ports?

Tout sauf les ports par défaut doit être autorisé explicitement en ajoutant le numéro de port ou un astérisque après le domaine autorisé:

content="default-src 'self' https://ajax.googleapis.com http://example.com:123/free/stuff/"

Ce qui précède entraînerait:

https://ajax.googleapis.com:123
                           ^^^^ Not ok, wrong port

https://ajax.googleapis.com - OK

http://example.com/free/stuff/file.js
                 ^^ Not ok, only the port 123 is allowed

http://example.com:123/free/stuff/file.js - OK

Comme je l'ai mentionné, vous pouvez également utiliser un astérisque pour autoriser explicitement tous les ports:

content="default-src example.com:*"

5. Comment gérer différents protocoles?

Par défaut, seuls les protocoles standard sont autorisés. Par exemple, pour autoriser WebSockets, ws://vous devrez l'autoriser explicitement:

content="default-src 'self'; connect-src ws:; style-src 'self'"
                                         ^^^ web sockets are now allowed on all domains and ports

6. Comment autoriser le protocole de fichier file://?

Si vous essayez de le définir comme tel, cela ne fonctionnera pas. Au lieu de cela, vous l'autoriserez avec le filesystemparamètre:

content="default-src filesystem"

7. Comment utiliser les scripts en ligne et les définitions de style?

Sauf autorisation explicite, vous ne pouvez pas utiliser de définitions de style en ligne, de code à l'intérieur de <script>balises ou dans des propriétés de balise comme onclick. Vous les autorisez ainsi:

content="script-src 'unsafe-inline'; style-src 'unsafe-inline'"

Vous devrez également autoriser explicitement les images encodées en base64:

content="img-src data:"

8. Comment autoriser eval()?

Je suis sûr que beaucoup de gens diraient que vous ne le faites pas, car «l'évaluation est mauvaise» et la cause la plus probable de la fin imminente du monde. Ces gens auraient tort. Bien sûr, vous pouvez définitivement percer des trous majeurs dans la sécurité de votre site avec eval, mais il a des cas d'utilisation parfaitement valides. Il suffit d'être intelligent pour l'utiliser. Vous le permettez ainsi:

content="script-src 'unsafe-eval'"

9. Que 'self'signifie exactement ?

Vous pourriez 'self'vouloir dire localhost, système de fichiers local ou quoi que ce soit sur le même hôte. Cela ne signifie rien de tout cela. Cela signifie des sources qui ont le même schéma (protocole), le même hôte et le même port que le fichier dans lequel la politique de contenu est définie. Servir votre site via HTTP? Pas de https pour vous alors, sauf si vous le définissez explicitement.

J'ai utilisé 'self'dans la plupart des exemples car il est généralement logique de l'inclure, mais ce n'est en aucun cas obligatoire. Laissez-le de côté si vous n'en avez pas besoin.

Mais attendez une minute! Je ne peux pas simplement l'utiliser content="default-src *"et en finir avec ça?

Non. Outre les failles de sécurité évidentes, cela ne fonctionnera pas non plus comme prévu. Même si certains documents affirment qu'il autorise tout, ce n'est pas vrai. Cela n'autorise pas l'inline ou les évales, donc pour vraiment, vraiment rendre votre site très vulnérable, vous utiliseriez ceci:

content="default-src * 'unsafe-inline' 'unsafe-eval'"

... mais j'espère que non.

Lectures complémentaires:

http://content-security-policy.com

http://en.wikipedia.org/wiki/Content_Security_Policy


6
Très bonne publication. Une chose: ce n'est pas évident ce qui se passe lorsque plusieurs directives sont spécifiées; les paramètres de style-src dans l'exemple 3 ont-ils priorité sur default-src? etc ...
track0

30
Donc, pour tout autoriser tout ce que le contenu seraitdefault-src *; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'; img-src * data: 'unsafe-inline'; connect-src * 'unsafe-inline'; frame-src *;
Arnold Roa

8
Il est important de savoir que cela content="default-src * 'unsafe-inline' 'unsafe-eval'"est nécessaire pour faire fonctionner certaines applications angulaires.
flanger001

2
@Mahesh Ce "blog" est plein de messages copiés depuis SO. Il semble peu probable que tant d'utilisateurs SO copient le contenu d'un blogueur inconnu - je sais que non.
Schlaus

2
Brève note concernant connect-srcet chemins: les barres obliques de fin sont obligatoires si vous souhaitez inclure un sous-chemin entier. Par exemple: le fichier http://foo.com/files/bar.txtsera bloqué si la source est http://foo.com/files, mais servi quand il esthttp://foo.com/files/
Griddo

15

APACHE2 MOD_HEADERS

Vous pouvez également activer Apache2 mod_headers, sur Fedora, il est déjà activé par défaut, si vous utilisez Ubuntu / Debian, activez-le comme ceci:

# First enable headers module for Apache2, 
# then restart the Apache2 service   
a2enmod headers
apache2 -k graceful

Sur Ubuntu / Debian, vous pouvez configurer les en-têtes dans le fichier /etc/apache2/conf-enabled/security.conf

#
# Setting this header will prevent MSIE from interpreting files as something
# else than declared by the content type in the HTTP headers.
# Requires mod_headers to be enabled.
# 
#Header set X-Content-Type-Options: "nosniff"

#
# Setting this header will prevent other sites from embedding pages from this
# site as frames. This defends against clickjacking attacks.
# Requires mod_headers to be enabled.
#
Header always set X-Frame-Options: "sameorigin"
Header always set X-Content-Type-Options nosniff
Header always set X-XSS-Protection "1; mode=block"
Header always set X-Permitted-Cross-Domain-Policies "master-only"
Header always set Cache-Control "no-cache, no-store, must-revalidate"
Header always set Pragma "no-cache"
Header always set Expires "-1"
Header always set Content-Security-Policy: "default-src 'none';"
Header always set Content-Security-Policy: "script-src 'self' www.google-analytics.com adserver.example.com www.example.com;"
Header always set Content-Security-Policy: "style-src 'self' www.example.com;"

Remarque: il s'agit de la partie inférieure du fichier, seules les 3 dernières entrées sont des paramètres CSP.

Le premier paramètre est la directive, les seconds sont les sources à mettre sur liste blanche. J'ai ajouté Google Analytics et un adserver, que vous pourriez avoir. De plus, j'ai trouvé que si vous avez des alias, par exemple, www.example.com et example.com configurés dans Apache2, vous devez également les ajouter à la liste blanche.

Le code en ligne est considéré comme dangereux, vous devez l'éviter. Copiez tous les javascripts et css dans des fichiers séparés et ajoutez-les à la liste blanche.

Pendant que vous y êtes, vous pouvez jeter un œil aux autres paramètres d'en-tête et installer mod_security

Lectures complémentaires:

https://developers.google.com/web/fundamentals/security/csp/

https://www.w3.org/TR/CSP/


2
J'ai pu ajouter ces mêmes directives à mon fichier .htaccess, car je n'ai pas la possibilité de modifier les configurations Apache sur mon hôte partagé. J'ai trouvé d'excellents outils pour ajuster ces paramètres sur report-uri.io/home/tools .
Michael McGinnis

Existe-t-il un moyen de résoudre celui-ci avec tomcat 7. J'ai essayé d'ajouter des filtres et je n'ai pas fonctionné.
Elshan

0

N'oubliez pas la police-src, elle fonctionne de la même manière que toute autre, mais si vous utilisez des polices chargées d'autres origines - assurez-vous de l'ajouter à la balise META

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.