De la sécurité des headers HTTP

Sécurité des headers HTTP

Salut à tous, on m’a conseillé de jeter un œil au site securityheaders.com récemment. Celui-ci permet de contrôler la sécurité des headers HTTP d’un site. Et en testant le site, non seulement je me suis rendu compte qu’il m’en manquait quelques-uns. Mais aussi que je ne vous ai jamais fait un point sur la sécurité des headers HTTP. C’est l’occasion !

Quelle sécurité des headers HTTP ?

Bon je ne vais pas vous faire un dessin. Si vous ne savez pas ce qu’est un header HTTP allez faire un tour sur le net (genre ici ou ). Ils ne concernent pas le site à proprement parler (HTML, PHP, JS, CSS) mais la couche précédente du modèle OSI (HTTP). Ces headers permettent au client (le navigateur) et au serveur (nginx) d’échanger des informations relatives à la gestion du site. Comme par exemple : l’authentification, le comportement du cache, les timeouts de connexions ou encore les cookies. Une partie de ces headers concernent directement la sécurité de votre site. On va les détailler une par un ci dessous.

Quels en-têtes pour la sécurité ?

X-Frame-Options

On va commencer par un simple : X-Frame-Options. Ce header serveur permet d’indiquer au navigateur si il peut charger du contenu dans des balises <frame>, <iframe> ou <object>. Ces balises sont considérées dangereuses car elles permettent de faire charger du contenu en provenance d’un autre site. Plus de détails sur le site de l’ANSSI.

Une bonne pratique consiste donc à indiquer à vos clients via votre serveur web que les frames ne pas autorisées. Un peu de documentation ici. Si votre site ne charge pas trop de contenu externe, vous pouvez à priori utiliser le réglage ci-dessous. Il autorise les frames uniquement depuis la même origine (url source). Donc si un pirate arrive à en insérer du code dans vos pages, c’est qu’il a déjà la main sur votre site…

add_header X-Frame-Options SAMEORIGIN;

X-Content-Type-Options

Celle-ci est assez simple, il s’agit d’indiquer au navigateur du client qu’il n’est pas censé analyser les MIME-Type des éléments dans la page. Et donc s’en remettre à ce que le serveur web lui indique. De la même manière que pour les frames vous devriez pouvoir régler celui-ci sans trop de risque à nosniff.

 add_header X-Content-Type-Options nosniff;

Cache-Control

Bien détaillé sur Wikipédia, cet en-tête indique au navigateur la politique de cache qu’il doit appliquer pour votre site. Cela parait anodin, mais si le contenu de votre site est sensible, notamment dans des parties du site nécessitant une authentification. Vous ne voulez peut être pas que le navigateur conserve une copie locale de ces parties qui seront accessible à tous les autres utilisateurs du poste. Cela peut être particulièrement critique pour des portails intranet d’entreprises accessible depuis n’importe quels « postes en libre service »).

Avant de régler ce header, il faut bien garder en tête que les mécanismes de cache sont parmi les plus efficaces pour améliorer les performances d’un site et donc le ressenti de vos utilisateurs. Il ne faut donc pas le régler bêtement à « Pragma: no-cache ». Je vous propose plutôt le paramétrage suivant :

 add_header Cache-Control "private, no-transform, must-revalidate";
  • Private : permet d’indiquer que le contenu ne doit être mis en cache que par le client final. Et l’interdire à un reverse proxy sur le chemin par exemple.
  • no-transform : pour interdire toute modification de contenu par les proxy sur le chemin. Par exemple pour ajouter une bannière de pub chez certains CDN ou proxy ou augmenter la compression des images pour diminuer la bande passante… Car oui, ça existe.
  • must-revalidate : oblige le navigateur à contrôler la présence de la page à jour sur le site avant de se servir du cache. Ce qui force l’affichage d’une erreur à l’utilisateur si la page qu’il cherche à afficher est présente en cache mais n’existe plus sur le serveur.

X-XSS-Protection

Allez encore une simple avant d’attaquer les gros morceaux. X-XSS-Protection est un header qui indique au navigateur de ne pas charger les requêtes en XSS. Notez que ce header est complété de façon beaucoup plus détaillée par la Content-Security-Policy qu’on va voir juste après. Pas grand chose à régler donc :

add_header X-XSS-Protection "1; mode=block";

Content-Security-Policy

Alors celle-ci, elle pique ! La Content-Security-Policy (dite CSP) permet d’indiquer au navigateur la politique à appliquer concernant les éléments à charger dans une page. Il est possible de détailler ces éléments type par type, et source par source.

Alors si vous proposez un site statique, entièrement hébergé chez vous et sans aucun contenu externe : ça se passera bien. Déjà, si vous avez un CMS avec quelques modules complémentaires et trois vidéo embarqués, ça va déjà être plus compliqué. Mais, si vous vous appelez lemonde.fr et que votre page d’accueil charge des éléments en provenance de plus de 20 domaines différents et qui changent potentiellement tous les 6 mois. En fonction de vos appels d’offres et prestataires, ça devient, très vite, très compliqué (voir très impossible).

Bref, dans les CSP vous allez devoir spécifier quels types d’éléments depuis quels sources sont autorisées. Ou quelle politique est appliquée par défaut, quand l’élément n’est pas listé. Il va donc falloir se poser la question directive par directive de quels sont les sites à autoriser. C’est heureusement bien documenté ici.

Malheureusement, la méthode la plus efficace pour mettre ça en place reste le « die & retry« … Sur une pré-prod de préférence ! C’est à dire que vous mettez une politique par défaut restrictive et vous regardez ce qui casse. Vous utilisez le débogueur de votre navigateur pour observer la casse et vous ajoutez ensuite ce qui manque… Jusqu’à ce que vous n’ayez plus d’erreurs dans les principaux navigateurs. Attention le comportement varie un peu entre Chrome et Firefox par exemple. Soyez vigilants pour les parties d’administrations de votre site qui peuvent charger des ressource externes différentes de la page principale… Voilà un exemple de à quoi pourrait ressembler votre CSP en mode simple :

add_header Content-Security-Policy "default-src 'self' ; script-src 'self' https://www.googletagmanager.com/ https://www.google-analytics.com/; img-src 'self' ; media-src 'self' https://www.youtube.com/; frame-src https://www.youtube.com/ https://wordpress.org/ ; font-src 'self' data: https://fonts.googleapis.com  https://fonts.gstatic.com";

Mais celle-ci il faudra vous la configurer vous même en fonction des dépendances de votre site…

Referrer-Policy

La Referrer-Policy permet d’indiquer au navigateur quel site référent indiquer lors des sorties de votre site. Et vous pouvez indiquez quels informations vous souhaitez envoyer dans le champ referrer. C’est utile, par exemple si avez une arborescence de domaine et que vous ne souhaitez indiquer que le top-domain. Ou aussi, si vous ne souhaitez pas envoyer les URL complètes car elles pourraient contenir des informations sensibles (dans un GET par exemple, et Shame-On-You si c’est le cas). A vous de voir ce que vous souhaitez indiquer… c’est bien documenté ici. Pour ma part j’ai mis :

add_header Referrer-Policy no-referrer-when-downgrade; 

Feature-Policy

L’option Feature-Policy permet d’indiquer au navigateur quels sont les fonctionnalités que votre site va utiliser (géolocalisation, webcam, vibreur, paiement). Dans le but d’empêcher un méchant pirate qui aurait réussi à injecter du code dans votre page d’activer la caméra de Mme Michu.

add_header Feature-Policy "geolocation 'self'; midi 'self';notifications 'self';push 'self';sync-xhr 'self';microphone 'self';camera 'self';magnetometer 'self';gyroscope 'self';speaker 'self';vibrate 'self';fullscreen 'self';payment 'self'";

Comme pour les CSP, cela dépend fortement de ce que propose votre site… comme fonctionnalités.

Expect-CT

Et pour finir un petit nouveau : Expect-CT. CT pour Certificate Transparency, dans le but de détecter les faux certificats x509 (doc anssi sur le sujet). Cela vous permet (en tant qu’administrateur du site) de détecter des certificats malicieux (ou en erreurs) qui serait proposé à vos clients. La fonctionnalité et encore un peu expérimentale… Mais il existe un mode reportOnly qui ne fait que signaler les erreurs vers un serveur tiers et ne bloque donc jamais le client. D’ailleurs, le site report-uri.com vous propose de gérer jusqu’à 10 000 remontées par moi, gratuitement. C’est un bon moyen pour commencer, il faut donc vous inscrire et ajouter l’en-tête suivant sur votre site.

add_header Expect-CT "max-age=0, report-uri='https://geekeriesdotorg.report-uri.com/r/d/csp/reportOnly'";

Et HTTPS la dedans ???

Et bien ça ne touche tout simplement pas à la sécurité des headers HTTP. On s’occupe juste des mécanismes de protection proposé par HTTP. Notez quant même que ces mécanismes ne servent presque à rien sans la mise en place d’HTTPS. Sinon n’importe quel attaquant en capacité d’interception pourrait alors les modifier.

En plus pour HTTPS, je l’ai déjà évoqué dans d’autres articles sur le blog : nginx, passage à HTTPS ou encore TLS 1.3 plus récemment. Si vous voulez gratter sur sujet, regardez du côté du HSTS, SSL Stapling et plus largement des options SSL de nginx.

Conclusion

Bref, encore un truc dont il faut se soucier lorsque vous mettez en ligne votre site internet… Si ce n’est pas le point le plus urgent d’un point de vue sécurité (priorité à la configuration du firewall, son patch management ou tout simplement la mise en place d’HTTPS), la sécurité des headers HTTP reste un point à ne pas négliger.

Une petite piste à regarder en ouverture si vous commencez à configurer votre serveur web. Vous pouvez partir de configurations toutes faites sur le site : nginxconfig.io. Ce dernier propose des fichiers de confs génériques et configurable pas trop mal foutus qu’il n’y a plus qu’a adapter. @+

2 commentaires on “De la sécurité des headers HTTP

  1. Bonjour,

    Merci pour l’article.

    > Et HTTPS la dedans ???
    >
    > Et bien ça ne touche tout simplement pas à la sécurité des headers HTTP

    Il est faux dire que HTTPS n’est pas lié aux en-têtes HTTP. Certes la configuration de la couche TLS se fait ailleurs, mais lorsqu’elle est faite, il est intéressant de l’indiquer aux navigateurs et de forcer l’utilisation de HTTPS.
    C’est la raison d’être de HSTS que vous évoquez plus loin. Cet en-tête se met en oeuvre par le positionnement d’un en-tête HTTP. Votre capture d’écran en début d’article illustre justement que l’en-tête « Strict Transport Security » est vérifié par securityheaders.com.

    • Alors oui, mais je ne suis pas sur de comprendre la remarque ?
      Effectivement HSTS est un bien un header HTTP en lien avec HTTPS. s’il y a besoin de préciser, à part ce header, la configuration « correcte » d’HTTPS sur un serveur est un sujet complétement disjoint de celui des headers d’HTTP (et liés à la sécurité) dont on parle dans cet article. C’est pour cela que je me permet cette façon de le présenter (et que je rajoute au moins 6 liens en rapport avec HTTPS par la suite, où on parle bien d’HSTS).
      Et bonus pour les futurs lecteurs, si vous voulez sécuriser votre site web : commencez par un HTTPS, hein ! les headers, c’est bien, il faut le faire, mais c’est moins urgent quand même…^^

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.