Définition
CSP est une politique de sécurité relative au contenu que votre site “distribue” vers l’utilisateur final, quelque soit son client web. Cette entête HTTP permet de contrôler très finement l’accès aux ressources de votre site et des ressources partagées par d’autres à-partir de votre site.
Cette politique de sécurité impose que le développement des codes CSS } et JS soit propre, c’est-à-dire “embarqué” par les balises HTML adéquates pour charger du code source correspondant, et non pas embarqués dans le code source HTML. On parle de code inline ; c’est cela qu’il faut éviter…
Le bénéfice de sécurité est vraiment important, mais regorge de difficultés conséquentes, car il est vraiment nécessaire de comprendre les impacts des différentes directives qui vont plus ou moins empêcher l’accès aux ressources !
Il faut aussi assimiler qu’avec une seule entête HTTP, il est possible d’avoir un éventail d’interactions qui ne sont pas anodines.
Il y a actuellement deux normes :
- CSP 1 est normalement supportée par l’ensemble des navigateurs connus, sauf Opera Mini
- CSP 2 est généralement bien supportée par l’ensemble des navigateurs, seul Firefox a un support partiel, et IE et Opera Mini n’ont pas de support du tout ! Si vous avez un problème d’affichage, mettez-à-jour votre client web - sauf pour les deux derniers suscités…
- une troisième version est en cours de travail auprès du W3C. Officiellement, aucun support pour aucun navigateur web !
Modes
Il y a deux modes possibles, et il est vraiment conseillé de commencer avec le premier, histoire de réaliser les tenants et aboutissants :
Content-Security-Policy-Report-Only
: ce mode est à considérer comme un mode de test, qui n’a pas d’impact sur votre site web, mais permet de tester les différentes directivesContent-Security-Policy
: est le mode d’application des directives
Directives
Il a vraiment beaucoup de directives, d’autant que selon la version de la politique CSP, certaines sont déclarées obsolètes…
La première directive à mettre-en-place est la directive par défaut :
default-src
: est la directive qui définit par défaut le comportement de l’entête CSP. - norme CSP 1 - Attention, seules certaines directives sont assujetties à cette directive par défaut :child-src
,connect-src
,font-src
,img-src
,manifest-src
,media-src
,object-src
,script-src
,style-src
etworker-src
!
Voici les autres directives qui peuvent être mises-en-place :
base-uri
: définit l’URI que le client web utilisera comme base de la page web affichée - norme CSP2 -block-all-mixed-content
: empêche que le client web (télé)charge du contenu sur le protocole HTTP alors que la page est consultée en mode HTTPSchild-src
: définit les sources valides relatives aux contenus autorisés - norme CSP2 -connect-src
: définit quelles sources sont valides pour les connexions de type XMLHttpRequest, WebSocket, et assimilées. - norme CSP 1 -disown-opener;
: assure qu’une ressource ne puisse être ouverte lors de sa consultation - norme CSP3 -font-src
: directive ayant un impact sur les polices à afficher. - norme CSP 1 -form-action
: définit l’interaction avec l’élément HTML form. - norme CSP2 -frame-ancestor
: directive pour les ressources partagées par les frames embarquées - norme CSP2 - c’est l’équivalent de l’entête X-Frame-Options…frame-src
: directive pour les ressources partagées par les frames embarquées. - norme CSP 1 - dépréciée en CSP2 - réintroduite dans CSP 3img-src
: directive ayant un impact sur les images à charger. - norme CSP 1 -manifest-src
: définit quel manifeste peut être appliquée à la ressource. - norme CSP3 -media-src
: directive pour les ressources audio, et vidéo. - norme CSP 1 -navigate-to
: directive pour contrôler les ressources autorisées à la navigation - norme CSP3 -object-src
: directive pour les ressources qui chargent des plugins, des applets et autres éléments embed. - norme CSP 1 -plugin-types
: directive qui définit le type des ressources qui peuvent être chargées. - norme CSP2 -referrer
: directive équivalent à l’entête Referrer - cette directive a ses propres mots-clés !reflected-xss
: directive pour filtrer les attaques de type XSS - équivalent de l’entête X-XSS-Protection - cette directive a ses propres mots-clés !report-to
: spécifie un jeton qui définit un groupe de rapports à envoyer. - norme CSP3 -report-uri:
: directive qui définit l’URL où reporter les violations de sécurité. - norme CSP 1 - dépréciée en CSP3 , au profit dereport-to
-require-sri-for
: directive qui oblige l’attribut SRI pour les scripts et autres styles. - cette directive a ses propres mots-clés !sandbox
: directive qui utilise une sandbox HTML pour protéger l’exécution des ressources. - cette directive a ses propres mots-clés ! - norme CSP 1 -script-nonce
: directive qui autorise l’exécution d’un script seulement s’il y a correspondance avec l’attributnonce
. cf : les explications liées au mot-clénonce
ci-dessous…script-src
: directive qui régit les scripts exécutables, tels que JS. - norme CSP 1 -style-src
: directive qui régit les feuilles de styles. - norme CSP 1 -upgrade-insecure-requests
: oblige toute requête faite en HTTP à basculer en HTTPS si une page est chargée en HTTPS.worker-src
: définit quelles URL peuvent être chargées en tant que Worker, Sharedworker ou ServiceWorker.
Il est très possible, du fait de l’évolution de la norme de cette entête que j’ai oublié la présentation de certaines directives… veuillez vérifier auprès du W3C.
Notes
- Du fait que la directive
default-src
n’a pas d’impact sur certaines directives, telles queframe-ancestor
,form-action
, si ces dernières ne sont pas spécifiées, alors l’émission de données correspondantes sera envoyée… - La directive
block-all-mixed-content
est évaluée après la directiveupgrade-insecure-requests
- La directive
child-src
remplace la directiveframe-src
- Si la directive
child-src
n’est pas définie, elle est influencée pardefault-src
- c’est le cas de toutes les directives assujetties à cette dernière - Il est préférable de l’utiliser pour les scripts “dépendants” plutôt que l’usage de la directive
script-src
. - Si les directives
frame-src
,work-src
ne sont pas spécifiées, la politiquechild-src
s’applique.
- Si la directive
- La directive
plugins-type
n’accepte pas le caractère wildcard*
; il faut définir un type MIME : e.g :application/pdf
!
==== Recommandations ===
- La première des recommandations est : Il n’y a rien de pire de ne rien faire que de spécifier plusieurs fois la même directive… seule la première directive est prise-en-compte !
- La deuxième est de démarrer avec la déclaration suivante :
default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self';
; et de voir comment cela réagit ! ;-) - Concernant la directive
object-src
, préférez l’usage du mot-clénone
, sauf à avoir l’absolu nécessité d’exécuter des scripts Flash, ou Silverlight. - Concernant les directives
block-all-mixed-content
etupgrade-insecure-requests
, il est recommandé d’activer ou l’une, ou l’autre, mais pas les deux ! - Attention à l’usage de la déclaration suivante :
script-src 'self'
qui peut ne pas être sûre en présence de JSONP. - Idéalement, utiliser la directive
report-uri
qui postera du contenu JSON pour relever les violations de sécurité, par vos propres moyens, ou au-travers d’un service fourni par un tiers.
Mots-clés
Aux directives, il est possible d’appliquer un ou plusieurs mots-clés :
*
: autorise toutes les ressources. Ce wilcard peut s’appliquer aussi dans l’écriture des schemes, des URL et des ports autorisés, tel que :*://*.domaine.xyz://
<= cet exemple signifie l’autorisation de toutes les ressources des différents sous-domaine, quelque soit le protocole utilisé, et sur n’importe quel port de connexion.'none'
: refuse toutes les ressources - C’est la politique à préférer, en terme de sécurité absolue, sur la directive par défaut !'self'
: autorise les ressources du domaine en cours ; ne gèrent pas les ressources de sous-domaines, s’ils existent… il faut les autoriser explicitement par l’ajout de l’URL correspondante ! - C’est la politique minimale à appliquer sur la directive par défaut.'strict-dynamic'
: autorisera les scripts à charger leurs dépendances sans avoir à les autoriser spécifiquement - norme CSP3 -'unsafe-inline'
: permet l’usage du code inline CSS ou JS.'unsafe-eval'
: permet l’évaluation de tout…'unsafe-hashed-attributes'
: autorisera les gestionnaires d’événements selon leur hash. - norme CSP3 -
Mots-clés relatifs à la gestion des données - dans chaque cas, il est strictement nécessaire de spécifier une URI :
blob:
: autorise l’usage de binairesdata:
: autorise l’usage des données relatives à certaines directives utilisées, telles que les directivesscript-src
,styles-src
,… cela peut être des images encodées en base64filesystem:
: autorise l’usage de ressources depuis le système de fichiers.https:
: oblige les ressources à être chargées absolument par le biais du protocole HTTPS.mediastream:
: autorise le chargement de streaming de médias audio, vidéo,…wss:
: autorise le chargement des websockets !
Mots-clés relatifs à la directive referrer :
origin
: le client web envoie toujours l’origine de l’entête vers le même siteorigin-when-cross-origin
: le client web enverra l’origine de l’entête uniquement vers le même site même lorsque les origines sont croisées.no-referrer
: n’envoie pas l’entêteno-referrer-when-downgrade
: n’envoie pas l’entête quand le client navigue depuis HTTPS vers HTTPsame-origin
: envoie l’entête si seulement vers le même siteunsafe-url
: envoie toujours l’entête vers tous.
Mots-clés relatifs à la directive reflected-xss :
allow
: désactive toute protection contre les attaques XSS.block
: bloque le chargement des ressources si une attaque XSS est détectéefilter
: filtre la charge XSS avant son exécution
Mots-clés relatifs à la directive require-sri-for :
script
: oblige l’attribut integrity pour les scriptsstyle
: oblige l’attribut integrity pour les stylesscript, style
: oblige l’attribut integrity pour les scripts et les styles
Mots-clés relatifs à la directive sandbox :
sandbox
: active la protection avec toutes les restrictions en place. Aucune des autres valeurs ne doit être spécifiée afin que toutes les restrictions soient respectées !allow-forms
: permet une page à soumettre un formulaireallow-pointer-lock
: évalue la gestion du pointeur de souris.allow-modals
: permet les interactions avec le client web.allow-popups
: autorise l’ouverture de popupsallow-same-origin
: permet à une page d’accéder à du contenu depuis le même siteallow-scripts
: permet à une page d’exécuter ses scriptsallow-top-navigation
: permet à une page de ???
Il existe deux mots-clés très spécifiques :
hash
: il permet d’autoriser un script, ou un style en particulier selon le hash définit… le hachage est calculé selon un des trois algorithmes SHA-2 (sha256, sha384 - politique minimale recommandée, sha512), encodé en base64. e.g. :style-src 'sha256-HashDigestHere='
nonce
: acronyme de Number used Once - Numéro utilisé une seule fois - ; il permet d’autoriser un script inline selon la valeur dynamique aléatoire autorisé.
Il est très possible, du fait de l’évolution de la norme de cette entête que j’ai oublié la présentation de certains mots-clés… veuillez vérifier auprès du W3C.
Recommandations
- Il est recommandé d’appliquer le mot-clé
https:
sur la directive par défaut, tel que :default-src: https:
. Cela désactive le code inline et oblige toute connexion en mode HTTPS seulement. - Il est clairement recommandé d’éviter l’usage du mot-clé
unsafe-inline
! Malheureusement, parfois certains scripts “embarqués” ou styles extérieurs nécessitent des données et autres codes qu’il est difficile de gérer finement ; c’est la solution du “moins pire” - Il est assurément recommandé de ne pas utiliser le mot-clé
unsafe-eval
! - Attention à l’usage du mot-clé
data:
: par ce biais, il peut remonter des contenus “dérivés” inhérents aux directivesobject-src
,script-src
,… - L’attribut
nonce
doit être unique, re-généré à chaque fois, et bien entendu doit être non trivial et non devinable !`
Risques
Les risques possibles sont liés à :
- Des erreurs de configuration, dues à des incompréhensions - d’où l’intérêt de tester avant l’application ;)
- l’application de politique trop permissive, tel que l’usage des mots-clés
unsafe-*
… - Utiliser le mot-clé
unsafe-inline
est l’équivalent de ne pas avoir de politique de sécurité ; quant à utiliser le mot-cléunsafe-eval
est assurément l’équivalent d’un trou béant dans votre site web où vous permettez à tout le monde de faire n’importe quoi… <= vous, voilà, prévenus !!! oui, j’exagère peut-être un peu… mais le risque est réel, et sérieux.
Examples
Content-Security-Policy: default-src https:
Il est possible de la définir par le biais de l’élément HTML meta, tel que :
<meta http-equiv="Content-Security-Policy" content="script-src 'self'">
nginx
add_header Content-Security-Policy "default-src 'self';" always;
relayd
Et, oui, malheureusement, httpd ne peut pas gérer les entêtes, ce sera son binôme relayd(8) que l’on utilisera !
match response header set "Content-Security-Policy" value "default-src 'self' data: 'unsafe-inline'; base-uri \*://domain.tld ; form-action 'self'; frame-ancestors 'none'; referrer no-referrer; reflected-xss block; sandbox allow-same-origin ; script-src 'self' cdnjs.cloudflare.com netdna.bootstrapcdn.com ;"
Documentations
- https://scotthelme.co.uk/csp-cheat-sheet/
- https://content-security-policy.com/
- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
- https://www.owasp.org/index.php/Content_Security_Policy
- https://openweb.eu.org/articles/content-security-policy
Autres sites intéressants
- https://report-uri.io
- Support actuel : http://caniuse.com/#search=csp