Content Security Policy

Utiliser une stratégie de sécurité du contenu (Content Security Policy)

Par DivUP le 27 janvier 2020

Le CSP (Content Security Policy) est un excellent moyen de diminuer les attaques XSS et les injections de contenu. Vous décidez des resources internes et externes que le navigateur a le droit de charger. Configurer une stratégie CSP nécessite simplement d'utiliser un en-tête HTTP Content-Security-Policy.

La mise en place d'une stratégie de sécurité du contenu avec CSP est extrêmement simple et efficace. CSP vous permet d'éliminer les moyens de réaliser des attaques XSS en permettant de spécifier les domaines autorisés à fournir des resources (scripts, images, CSS...) pour la page visitée.

Configuration

Plusieurs possibilités pour inclure l'en-tête Content-Security-Policy.

Configuration Apache
# Content-Security-Policy
<IfModule mod_headers.c>
    Header set Content-Security-Policy "default-src 'self'"
</IfModule>
# /Content-Security-Policy
Configuration Nginx
add_header Content-Security-Policy "default-src 'self';"
Fichier .htaccess
# Content-Security-Policy
<IfModule mod_headers.c>
    Header set Content-Security-Policy "default-src 'self'"
</IfModule>
# /Content-Security-Policy
Header (PHP)
header("Content-Security-Policy: default-src 'self'");
Meta Tag
<meta http-equiv="Content-Security-Policy" content="default-src 'self'" />

Page d'exemple

Pour notre article, nous utilisons la page suivante :

<!doctype html>
<html lang="fr">
    <head>
        <title>Content Security Policy</title>

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

        <!-- Local resources -->
        <link rel="stylesheet" href="css/style.css" type="text/css" />
        <script type="text/javascript" src="js/script.js"></script>

        <!-- External resources -->
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/styles/default.min.css" type="text/css" />
        <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/highlight.min.js"></script>

        <!-- Inline CSS -->
        <style>
            h1 {
                color:#CC0000
            }
        </style>
    </head>
    <body>
        <h1>CSP Page</h1>

        <!-- Inline CSS -->
        <p style="font-weight: bold">Content Security Policy example page</p>

        <!-- External image -->
        <img src="https://fr.wikipedia.org/static/images/project-logos/frwiki.png" alt="Wikipedia" />

        <!-- Inline Script -->
        <script type="text/javascript">
            console.log('ok');
        </script>
    </body>
</html>

Application

Si vous copiez la page d'exemple dans un fichier html, la majorité des resources sont bloquées. Vous obtenez dans la console du navigateur :

Blocage des resources par le navigateur (CSP)
Resources locales

Considérons la directive CSP suivante :

default-src 'self'

Nous indiquons ici au navigateur de ne charger que les resources locales, c'est à dire les fichiers Javascript et CSS herbergés sur notre serveur. Dans notre page d'exemple cela correspond à :

<!-- Local resources -->
<link rel="stylesheet" href="css/style.css" type="text/css" />
<script type="text/javascript" src="js/script.js"></script>

Cette stratégie est la plus restrictive et sécurisée qui soit (après la valeur "none" mais c'est un peu excessif). Par défaut nous n'autorisons que les resources locales, les scripts et CSS inline sont ignorés.

Style inline

Notre page contient des styles en lignes dans le header et dans la page. Avec la directive précedente ils sont ignorés. Nous pouvons autoriser le style inline grâce à la valeur unsafe-inline de la directive style-src :

default-src 'self'; style-src 'self' 'unsafe-inline'

Avec cette stratégie, nos styles en lignes sont maintenant interprétés :

<!-- Inline CSS -->
<style>
    h1 {
        color:#CC0000
    }
</style>
<!-- Inline CSS -->
<p style="font-weight: bold">Content Security Policy example page</p>
Script inline

Notre page contient un script en ligne ignoré avec notre politique par défaut. Il est cependant possible de d'accepter les scripts inline par le biais de la valeur unsafe-inline de la directive script-src :

default-src 'self'; script-src 'self' 'unsafe-inline'

Nous autorisons ainsi la portion de code suivante :

<!-- Inline Script -->
<script type="text/javascript">
    console.log('ok');
</script>

Dans la pratique il est souvent complexe de ne pas autoriser les scripts en ligne, mais pour une stratégie de sécurité du contenu optimale il faut tendre à ne plus les utiliser.

CSS externe

Nous tentons de charger une resource CSS herbergée sur un serveur distant (cdnjs.cloudflare.com). Cette resource est automatiquement bloquée. Il est nécessaire de l'autoriser. Il faut pour cela indiquer le domaine concerné pour style-src :

default-src 'self'; style-src 'self' cdnjs.cloudflare.com

Cette stratégie nous permet de charger le CSS externe spécifié dans le header :

<!-- External resources -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/.../styles/default.min.css" type="text/css" />
Script externe

Nous souhaitons charger un Script herbergé sur un serveur distant (cdnjs.cloudflare.com). Cette resource est bloquée par défaut. Il nous faut l'autoriser :

default-src 'self'; script-src 'self' cdnjs.cloudflare.com

Cette stratégie nous permet de charger le Script spécifié dans le header :

<!-- External resources -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax.../highlight.min.js"></script>
Image externe

Pour finir, une image externe doit apparaître dans la page. Elle est également bloquée par défaut. Nous l'autorisons via img-src :

default-src 'self'; img-src 'self' fr.wikipedia.org

Nous acceptons ainsi l'affichage des images issues du domaine fr.wikipedia.org :

<img src="https://fr.wikipedia.org/static/images/project-logos/frwiki.png" alt="Wikipedia" />

Autres directives

Dans notre page d'exemple nous avons abordés les directives CSP (version 1) suivantes :

  • default-src : politique par défaut, utilisée partout sauf si surchargée par une directive plus précise
  • style-src : la politique dédiée aux styles (CSS)
  • script-src : la politique dédiée aux scripts
  • img-src : la politique dédiée aux images

CSP présente d'autres directives à utiliser selon vos besoins :

  • object-src : la politique dédiée aux plugins (éléments object, embed, ou applet)
  • media-src : la politique dédiée aux medias (éléments video, audio, source, ou track)
  • 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

Toutes les directive acceptent les valeurs none, self et une liste de domaine.

Les directives style-src et script-src acceptent également la valeur unsafe-inline. Il est possible d'indiquer unsafe-eval avec script-src pour autoriser l'utilisation de la méthode eval().

La directive img-src accepte data: pour les images en base64 (script-src 'self' data:)

D'autres directives existent en CSP version 2 et 3 (form-action, child-src...). Retrouvez l'ensemble des directives sur MDN Web Docs.

Stratégie de sécurité

Pour afficher complétement notre page d'exemple, nous arrivons finallement à la stratégie de sécurité suivante :

default-src 'self'; style-src 'self' 'unsafe-inline' cdnjs.cloudflare.com; script-src 'self' 'unsafe-inline' cdnjs.cloudflare.com; img-src 'self' fr.wikipedia.org

Cette stratégie d'exemple n'est évidemment pas la plus sécurisée. Il est conseillé d'éviter les styles et scripts "inline" ainsi que l'utilisation de resources externes, cela peut souvent être évité.

La mise en place de CSP sur un site existant peut donc être extrêmement complexe, une politique moins restrictive (unsafe-inline) sera certainement nécessaire. L'avantage est qu'une fois établie vous maîtrisez les resources externes et le respect des bonnes pratiques pour les intégrations futurs.

Dans tous les cas n'oubliez jamais de vérifier la console du navigateur pour adapter si besoin votre stratégie de sécurité du contenu lors de sa mise en place.

Google Analytics

Si comme une grande majorité de sites vous implémentez Google Analytics, vous pouvez appliquer la stratégie de base suivante :

default-src 'self'; script-src 'self' 'unsafe-inline' www.googletagmanager.com www.google-analytics.com; img-src 'self' www.google-analytics.com
Monitoring

Surveillez la disponibilité de votre site

Soyez alerté en temps réel des anomalies liées à la disponibilité de votre site ou application web. Avec DivUP choisissez la surveillance continue et détectez lorsque votre site est indisponible (problème réseau, panne de serveur...). En savoir plus...

Websites

240 sites surveillés

Requests

207360 requêtes par jour

Notifications

2160 notifications