Content Security Policy, c'est quoi ?

La sécurité par affinage.
CSP ou Content Security Policy, c'est une manière très simple de dire ce qu'une page web est censée faire.
Pour moi celà va de paire avec la Feature Policy. Les deux sont censées décrire le comportement de la page mais le premier va se concentrer sur le DOM alors que le second va décrire les fonctionnalités du navigateur.
Je vais décrire chacune un peu plus précisément. Concrètement ce sont des entêtes HTTP envoyés par le serveur.

Comme sur l'image on peut voir l'entête http content-security-policy et elle contient plusieurs parties.
default-src, script-src .. Cela décrit les sources possibles c’est-à-dire qui doivent être acceptés par le navigateur.

On va prendre l'exemple de script-src, Si il contient unsafe-eval il va autoriser l'utilisation de la fonction eval, sinon cela va générer une erreur CSP.


Un autre exemple toujours avec script-src si on définit unsafe-inline il sera possible d'utiliser l'attribut style sur un élément du DOM. Dans le cas contraire cela va générer une erreur CSP. Il est d'ailleurs recommandé de ne pas utiliser des éléments styles inline et de définir uniquement le CSS par fichier puisque la source peut en être vérifiée. De plus il est possible de modifier des attributs CSS par JavaScript avec CSS Object Model sans déclencher de règle CSP car ils sont de source sures en théorie selon votre implémentation.

D'ailleurs la règle ne contient pas unsafe pour rien dans son nom.

Voici donc un petit descriptif des règles:

pour chaque directive (script-src, style-src,...) il est possible de
  • spécifier la même origine ou sous domaine avec 'self'
  • mettre une url sans apostrophe
Les directives sont les suivantesIl y en a pas mal alors comment je me débrouille avec tout ça ? C'est très simple, il faut dès le début du projet définir les règles les plus stricts.
Donc uniquement default-src: 'self'
Au fur et à mesure que le projet avance il faudra autoriser ce qui est nécessaire seulement.

Par exemple le plugin bootstrap-fileinput, injectant des images dans le DOM sans url (données en base64) il faut autoriser l'utilisation de BLOB (données binaires larges) :
'media-src: 'self' blob:

Feature Policy

Je vous en ai parlé juste avant. En gros c'est la même chose avec les fonctionnalités du navigateur. Il faut donc définir la règle la plus stricte, puis autoriser uniquement ce qui est nécessaire:

feature-policy: autoplay 'none'; fullscreen 'none'; layout-animations 'none'; legacy-image-formats 'none'; midi 'none'; navigation-override 'none'; oversized-images 'none'; picture-in-picture 'none'; sync-xhr 'none'; accelerometer 'none'; ambient-light-sensor 'none'; battery 'none'; camera 'none'; display-capture 'none'; document-domain 'none'; encrypted-media 'none'; execution-while-not-rendered 'none'; execution-while-out-of-viewport 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; publickey-credentials-get 'none'; usb 'none'; vr 'none'; wake-lock 'none'; xr-spatial-tracking 'none'; Notez que pour autoriser les requêtes Ajax il faudrait mettre sync-xhr 'self'; par exemple.

Pour résumer :
  • Toujours être le plus restrictif possible
  • Ne pas se reposer uniquement sur un seul système de sécurité, les règles CSP sont juste une forme de règle de sécurité parmi d'autres
  • Les entêtes HTTPS sont très importantes, il est nécessaire de connaître les différentes existantes.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy https://developer.mozilla.org/fr/docs/Web/HTTP/CSP

mardi 5 octobre 2021