Renforcer la sécurité de son site avec l’en-tête Content Security Policy

La sécurité de votre site n'est plus une option. Si le certificat SSL et les mises à jour régulières sont indispensables, les en-têtes HTTP le sont tout autant. Dont l'en-tête Content Security Policy.

Cet article prend 7 minutes à lire et comporte 1532 mots.

Depuis des années, Chrome et Firefox tentent d’o­rien­ter les inter­nautes vers des sites sécu­ri­sés. Edge en fait autant, et Opera pro­pose une exten­sion dans cette optique.

Mais le https et le cer­ti­fi­cat SSL qui va avec ne sont que l’un des outils mis à dis­po­si­tion pour sécu­ri­ser un site web. Et si vous n’al­lez pas plus loin, votre site ne sera pas sécu­ri­sé, loin s’en faut. Vous n’ob­tien­drez pro­ba­ble­ment pas un A+ en tes­tant la sécu­ri­té de votre site avec des outils tels que Qualys de SSL Labs ou avec Security Headers.

Ces deux outils ne se font pas concur­rence, ils se com­plètent. Autant Qualys va se foca­li­ser sur le cer­ti­fi­cat, les pro­to­coles (HSTS, OCSP Stapling, TLS…), autant Security Headers ne va s’oc­cu­per que des en-têtes de votre site web pour déter­mi­ner à quel point votre site est sécurisé.

Et l’une de ces en-têtes, c’est… je vous la donne en mille — Content Security Policy. Bien, me direz-vous. Mais…

L’en-tête Content Security Policy expliquée

Quelle est l’utilité de l’en-tête Content Security Policy ?

Cette en-tête contri­bue à réduire les attaques XSS et les injec­tions de conte­nu. C’est vous qui déci­dez des res­sources — internes et externes — que le navi­ga­teur a la per­mis­sion de char­ger et d’exécuter.

Les sites de Facebook, de Twitter ou du Nouvel Obs pour ne citer qu’eux uti­lisent l’en-tête Content Security Policy, avec des règles plus ou moins strictes.

Et voi­ci ce qui se passe quand une des règles n’est pas suivie :

Violation des règles de l’en-tête 

Mais atten­tion ! Ce n’est qu’un outil, c’est à vous que revient la déci­sion de char­ger ou de ne pas char­ger, d’exé­cu­ter ou de ne pas exé­cu­ter une res­source. Et donc, régu­liè­re­ment, en amont, de véri­fier qu’il n’y ait pas de code mali­cieux bien caché dans une exten­sion, un ser­vice en ligne ou dans un thème… Opération fas­ti­dieuse certes, mais indis­pen­sable. Parce que même si vos res­sources per­son­nelles sont clean, un script héber­gé ailleurs peut tou­jours être infec­té, à des­sein ou accidentellement.

Ceci dit, je ne vous conseille pas de réa­li­ser cette opé­ra­tion manuel­le­ment, mais plu­tôt en uti­li­sant un outil tel que Virus Total. Nouvelle exten­sion, nou­veau thème ? Ayez le réflexe Virus Total (asso­cié à une exten­sion de sécu­ri­té telle que Wordfence) et dor­mez sur vos deux oreilles !

Le contenu de l’en-tête Content Security Policy

Que doit conte­nir cet en-tête ? A mini­ma, de quoi char­ger scripts, styles et images avec le même nom de domaine (ou de sous-domaine). Pour un site dont l’url est https://mon-domaine.com/ par exemple, tout ce qui est héber­gé dans les sous-dos­siers (https://mon-domaine.com/wp-content/ prin­ci­pa­le­ment). Avec la direc­tive default-src, c’est le mot clé base-uri qui s’en char­ge­ra si vous avez implé­men­té la balise <base> sur votre site. Sinon, le mot clé 'self' (quotes incluses) s’en occupera.

Ce qui donne cette en-tête :

Content-Security-Policy: default-src base-uri 'self'

Avec cette décla­ra­tion, nous avons une police de sécu­ri­té a mini­ma, mais qui ne suf­fi­ra pas pour la grande majo­ri­té des sites web.

Heureusement, on peut aller plus loin, et défi­nir une ou des sources auto­ri­sées pour chaque type de conte­nu. Pour les scripts, les styles, les for­mu­laires, les images, les médias (Youtube, Vimeo…), les iframes, les polices de carac­tères, la connec­tion à des API, etc.

Par contre, de base, vous ne pour­rez pas accep­ter l’exé­cu­tion de scripts inclus dans la page, à moins de créer une faille dans la sécu­ri­té. Pour auto­ri­ser un tel script, il vous fau­dra soit leur attri­buer une nonce, soit cal­cu­ler leur empreinte, enco­dée via le pro­to­cole sha. Vous ne pour­rez pas non plus exé­cu­ter le code lié à un évé­ne­ment tel que onclick ou onload sans lui attri­buer son empreinte sha dans l’en-tête.

Vous trou­ve­rez des exemples simples ain­si qu’une une liste exhaus­tive des direc­tives, avec leur com­pa­ti­bi­li­té par navi­ga­teur (tout n’est pas par­fait en ce bas monde) sur le site Mozilla.

Nonces et SHA

WordPress uti­lise les nonces dans d’autres cir­cons­tances que celles qui nous inté­ressent, pour ren­for­cer la sécu­ri­té des for­mu­laires par exemple. Le nonce est en fait un jeton à usage unique, détruit après avoir été uti­li­sé.

Les nonces sont des chaînes de carac­tères géné­rés aléa­toi­re­ment qui n’ont pas voca­tion à être réuti­li­sés. C’est ce qui fait leur force, ils changent (ou devraient chan­ger) à chaque char­ge­ment de la page. Mais — revers de la médaille — l’u­sage de nonces inter­dit une décla­ra­tion unique depuis votre ser­veur, à moins d’u­ti­li­ser en per­ma­nence les mêmes nonces, ce qui en rédui­rait consi­dé­ra­ble­ment l’efficacité.

Enfin, un vir­tuose du code pour­rait peut-être (sûre­ment ?) créer des règles pour géné­rer en live les nonces en uti­li­sant les res­sources du ser­veur web, mais ce n’est pas à la por­tée du com­mun des mor­tels. Ceux qui peuvent confi­gu­rer cor­rec­te­ment un ser­veur web ne sont déjà pas légion…

La décla­ra­tion dans les balises se fait sous forme d’at­tri­but : nonce="…", la décla­ra­tion dans l’en-tête com­prend le pré­fixe nonce- sui­vi du nonce lui-même, le tout entre quotes simples (exemple : 'nonce-ca506d8715').

Même si l’en­cryp­tage via sha256 est le plus sou­vent uti­li­sé, notez que l’en-tête Content Security Policy auto­rise l’u­ti­li­sa­tion de sha384 et de sha512. Contrairement aux nonces, l’en­co­dage sha est fixe : une chaîne de carac­tères don­ne­ra inva­ria­ble­ment la même chaîne en sha (256/384/512).

C’est une sécu­ri­té dans le sens où il a fal­lu réa­li­ser l’o­pé­ra­tion d’en­co­dage avant de construire l’en-tête — et que vous êtes sup­po­sés avoir véri­fié votre code avant de l’en­co­der. Lors de l’en­co­dage, seul le conte­nu inclus entre les balises <script> et </script>, ou inclus entre les quotes doubles pour un évé­ne­ment doit être uti­li­sé.

La décla­ra­tion dans l’en-tête com­prend le pré­fixe sha256- / sha384- / sha512- sui­vi de la chaîne cryp­tée enco­dée en base 64, le tout entre quotes simples. Un exemple : 'sha256-Aajrk2aqPW2es8Zhh7RGO98KAFtogitkC5mSBKgzFd0='.

Une extension pour gérer l’en-tête Content Security Policy

J’ai cher­ché dans le dépôt WordPress une exten­sion gérant cette en-tête, mais en vain. Il en existe bien sûr, mais elles ne répondent pas à mon besoin (insé­rer les nonces à la volée, cal­cu­ler le sha des scripts inclus et des évé­ne­ments, récu­pé­rer les sources externes sûres, construire l’en-tête…) — alors j’en ai créé une 😉 et je l’ai nom­mée CSP ANTS&ST pour Content Security Policy — Add Nonces To Script & Style Tags.

Oui je sais, c’est une manie chez moi, quand je ne trouve pas, j’ai ten­dance à créer pour mes besoins… et à par­ta­ger ensuite — comme pour l’ex­ten­sion stop XML-RPC Attacks — tou­jours en lien avec la sécu­ri­té d’ailleurs !

Que fait exac­te­ment cette exten­sion ? Elle scanne votre page (enfin, son conte­nu), insère les nonces dans les balises script et style, cal­cule le SHA256 (enco­dé en base64) des évé­ne­ments en ligne (onclick et onload) et construit l’en-tête Content Security Policy pour chaque page, en fonc­tion de son contenu.

Je l’ai tes­tée sur un ser­veur Plesk (bundle Nginx / Apache), sur un ser­veur open­li­tes­peed avec lscache acti­vé… a prio­ri tout fonc­tionne — pour le moment, mais je n’ai pas de vidéo embar­quée, je ne com­mu­nique pas non plus avec d’autres ser­veurs via XHR ou quelque autre webservice.

Voici un exemple d’en-tête pro­duit par l’extension :

content-security-policy: base-uri 'self' https://secure.gravatar.com/avatar/ https://fonts.googleapis.com/ data:; object-src 'none'; script-src https: 'nonce-ca506d8715' 'nonce-ec261423d8' 'nonce-50394a2304' 'unsafe-hashes' 'sha256-Aajrk2aqPW2es8Zhh7RGO98KAFtogitkC5mSBKgzFd0=' 'strict-dynamic'

C’est basique, mais ça fonc­tionne. Seules les res­sources décla­rées et donc auto­ri­sées pour­ront être uti­li­sées sur la page.

Mais comme je vous l’ai déjà dit plus haut dans l’ar­ticle, cette sécu­ri­té ne vaut que si vous avez préa­la­ble­ment véri­fié que vos scripts et styles n’in­cluent pas de code mali­cieux.

À venir dans l’extension CSP ANTS&ST

Je n’ai pas implé­men­té — loin s’en faut — toutes les fonc­tion­na­li­tés offertes par l’en-tête Content Security Policy. On peut même dire que je n’ai implé­men­té que le strict mini­mum pour une uti­li­sa­tion générique.

Dans un pre­mier temps, je vais m’at­ta­cher à ne décla­rer que ce qui doit réel­le­ment être décla­ré — nul besoin par exemple d’as­si­gner une nonce à un script externe à la page, héber­gé sur le domaine ou sur un domaine de confiance.

Les pro­chaines direc­tives que je met­trai en œuvre sont form-action pour les for­mu­laires, child-src — ou media-src, à voir laquelle est la plus per­ti­nente — pour auto­ri­ser le conte­nu embar­qué (Youtube, Vimeo, Twitter…). Et pro­ba­ble­ment font-src, pour limi­ter l’u­sage de https://fonts.googleapis.com/ aux polices de carac­tères, de même que connect-src pour les connec­tions via XHR, WebSockets et EventSource (pour les cartes Google Maps par exemple).

Je vais éga­le­ment revoir le code, afin de le sim­pli­fier et de fac­to­ri­ser tout ce qui peut l’être, pour en faci­li­ter la lec­ture et la main­te­nance, et pour des temps d’exé­cu­tion plus courts.

Une page d’op­tions est en ges­ta­tion et me parait indis­pen­sable, pour évi­ter de perdre du temps à tes­ter à chaque nou­velle page si telle ou telle res­source est pré­sente, si telle ou telle action doit être effec­tuée ou pas, si l’on est sur un ser­veur Nginx, Apache, Openlitespeed, si autop­ti­mize est acti­vé, ou Lscache, avec quels réglages… 

Mais avant, je pré­fère pour­suivre l’im­plé­men­ta­tion de fonc­tion­na­li­tés essen­tielles pour avoir une idée plus exacte de ce que doit conte­nir cette page d’options.

Et maintenant…

Que vous savez tout (ou presque) sur l’en-tête Content Security Policy, c’est à vous de jouer ! Implémentez l’en-tête dans votre .htaccess, dans le fichier de confi­gu­ra­tion de votre ser­veur web, dans l’in­ter­face idoine pré­vue par votre héber­geur, ou plus sim­ple­ment, en ins­tal­lant et en acti­vant l’ex­ten­sion CSP ANTS&ST.

Et si vous avez une ques­tion, une sug­ges­tion ou si vous vou­lez par­ta­ger votre propre expé­rience, direc­tion les commentaires !

Retour en haut
We use cookies in order to give you the best possible experience on our website. By continuing to use this site, you agree to our use of cookies.
Accept