Comment implémenter Content Security Policy

Après avoir découvert l’intérêt de CSP pour se prémunir des risques en lien avec l’injection de contenus sur vos pages web, je vous propose des éléments techniques sur l’implémentation de CSP, mais aussi des réflexions sur la méthodologie à adopter. 

Nous l’avons vu dans notre premier billet dédié à la Content Security Policy, CSP est un simple header HTTP, donc pas de grande difficulté technique de ce côté pour la mise en place. Par exemple pour Apache, c’est une simple ligne de configuration :

<IfModule mod_headers.c>
 Header set Content-Security-Policy "script-src 'self' https://www.domainedeconfiance.com"
</IfModule>

Pour vous y retrouver avec les différentes options, certains générateurs pourront vous apporter une aide précieuse, par exemple celui de Report URI ou encore cspisawesome.com
Mais ne vous lancez pas sans réflexion : la moindre erreur de configuration de CSP pourrait entraîner des dysfonctionnements importants sur votre site !

Heureusement, vous pouvez utiliser le header Content-Security-Policy-Report-Only, équivalent de Content-Security-Policy, mais qui, comme son nom l’indique, se contentera de remonter des informations en cas de violation de la politique (sans  conduire à un blocage donc). Passer par le mode report only est donc un excellent moyen de tester vos configurations.
Vous pouvez tout à fait cumuler Content-Security-Policy et Content-Security-Policy-Report-Only, très utile pour avoir une approche incrémentale pour tendre vers une politique de moins en moins permissive.   

Avant de mettre en place CSP, pensez à vos workflows : qui peut ajouter des contenus ? sous quels délais ? avec quelle validation ? qui est chargé de mettre à jour CSP ?
Cela vous permettra d’éviter des écueils importants. Pensez notamment aux systèmes de tags manager, qui offrent généralement une souplesse importante aux équipes marketing, mais dont le fonctionnement sera souvent incompatible avec CSP.

Content Security Policy, les options disponibles (directives et valeurs)

default-src la politique par défaut, utilisée partout sauf si surchargée par une directive plus précise
script-src la politique dédiée aux scripts
object-src la politique dédiée aux plugins (éléments object, embed, ou applet)
style-src la politique dédiée aux styles (CSS)
img-src la politique dédiée aux images (element img, mais aussi url() ou image() depuis une CSS, ou encore élément link lié à une image (ex: rel=”icon”)
media-src la politique dédiée aux medias (éléments video, audio, source, ou track)
frame-src la politique dédiée aux frames (éléments iframe ou frame).
NB : directive dépréciée par CSP level 2
font-src la politique dédiée aux polices de caractères
connect-src la politique dédiée à l’établissement de connexions depuis un objet XMLHttpRequest ou une WebSocket
report-uri Permet de définir une URI à laquelle sera envoyée les éventuels rapports de violation de votre CSP : si une ressource est bloquée par un navigateur visitant la page, le navigateur enverra un rapport avec des informations détaillées à cette URI.
Attention à la gestion des rapports : si votre trafic est important, le volume pourrait être considérable !

Les directives xxx-src peuvent accepter comme valeur : ‘none’, le caractère * (tout autoriser) ou une combinaison de ces valeurs :

  • self’ (le domaine courant)
  • liste de domaines (séparés par une virgule, avec utilisation possible de *.mondomaine.com )
  • data: (par exemple pour autoriser les images en base64)

script-src et style-src acceptent également la valeur ‘unsafe-inline’ pour autoriser l’utilisation de scripts ou de styles inline dans votre HTML.

Attention donc aux effets de bord que vous pourriez rencontrer avec une directive “default-src” qui ne propose pas de valeur ‘unsafe-inline’. L’utilisation d’un “default-src” non complétée d’un style-src ‘unsafe-inline’ conduira donc au blocage des styles inline !

Pour finir, les directives suivantes ont été introduites avec CSP level 2 : base-uri, child-src, form-action, frame-ancestors, plugin-types. CSP 2 permet également d’autoriser spécifiquement certains scripts ou styles inline par exemple, en offrant donc davantage de granularité à ce sujet. Pour en savoir plus vous pouvez consulter la spécification, qui nous précise également ce passage que je vous invite à retenir :

In order to protect against Cross-Site Scripting (XSS), web application authors SHOULD include:

  • include a default-src directive, which covers both scripts and plugins.

In either case, authors SHOULD NOT include either ‘unsafe-inline’ or data: as valid sources in their policies. Both enable XSS attacks by allowing code to be included directly in the document itself; they are best avoided completely.

En résumé : pour se prémunir des attaques XSS vous devez utiliser default-src ou la combinaison  de script-src et object-src, et ne pas autoriser unsafe-inline ou data: dans ces politiques.

CSP, un outil puissant, à utiliser prudemment

Pour conclure sur CSP, on retiendra que c’est un outil très puissant, dont les bienfaits ne s’arrêtent pas à la couche de sécurité supplémentaire apportée. Même si sa mise en oeuvre sur des sites web d’envergure peut apparaître complexe, CSP propose un mode Report Only qui permettra d’avoir une approche progressive et solide.
Et quand on sait la fréquence des failles XSS et les problèmes que peuvent poser les contenus de tierces parties, l’effort que cela représente paraît bien moindre.

Si vous souhaitez aller plus loin, vous trouverez une liste très intéressante de ressources sur le dépôt CSP-useful.

2 réflexions au sujet de « Comment implémenter Content Security Policy »

  1. Merci pour les 2 articles qui éclairent comment fonctionnent et sont implémentées les CSP (les articles en français sont encore rares sur ce sujet).

    Une remarque : frame-src est noté deprecated (en CSP 2) et devrait être remplacé par child-src (c’est d’ailleurs de cette façon que je l’ai implémenté dans Dotclear, côté backend pour l’instant).

    1. Merci Franck pour ce retour. Effectivement, le manque de littérature en FR à ce sujet nous a incité à détailler ce sujet ici, ayant régulièrement des questions sur la recommandation que nous effectuons sur CSP sur notre outil d’analyse.
      Merci pour la précision sur frame-src, j’avais effectivement raté cela. J’ai rajouté une note avec lien vers la spécification qui mentionne child-src.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

*