Sécurité Web 12 Mars 2022

À quoi servent les en-têtes de sécurité HTTP ?

Image de présentation pour

Les en-têtes HTTP indiquent au navigateur web la manière de se comporter suivant différentes situations. Certaines de ces situations peuvent introduire des faiblesses de sécurité. Cet article a pour objectif de présenter ces en-têtes, dits “de sécurité”, et de comprendre leur fonctionnement.

Les en-têtes de sécurité

Strict-Transport-Security (HSTS)

Afin de garantir la confidentialité et l’intégrité des échanges, chaque requête vers un site web doit être réalisée sur un flux chiffré en HTTPS. La bonne pratique consiste à rediriger systématiquement l’utilisateur de HTTP vers HTTPS (avec un code 301). Cela sous-entend que le navigateur commence par exécuter une première requête en HTTP avant d’être redirigé vers la version HTTPS du site. C’est la première requête qu’un attaquant va utiliser pour son attaque de type Man-In-The-Middle : il redirige l’utilisateur vers un autre site (sous son contrôle) ou encore le force à rester sur la version en clair du site.

L’en-tête HTTP Strict-Transport-Security (HSTS) indique au navigateur qu’il doit se rappeler d’aller sur le site directement en HTTPS lors des prochaines visites. Il se présente de la forme suivante :

Strict-Transport-Security: max-age=<TEMPS>; <includeSubDomains;> <preload;>
  • max-age indique le temps de conservation de l’information, il doit être positionné assez longtemps entre deux visites sur le site (par exemple 1 ans (31536000) ou 2 ans (63072000)), la valeur peut être augmenté progressivemen en vérifiant si des problèmes surviennent
  • includeSubDomains indique si les sous-domaines (du domaine actuel) doivent aussi être inclus
  • preload indique que le navigateur peut partager cette information sur une base de données commune du navogateur (il ne fait pas partie de la spécification)

Pour le déploiement, il est recommandé d’augmenter progressivement le max-age en vérifiant si des problèmes surviennent.

Exemple d&rsquo;utilisation du HSTS
Exemple d’utilisation du HSTS

X-Frame-Options

Une page web peut inclure une autre page à l’aide de la balise iframe (frame, embed ou encore object). Un utilisateur peut se faire piéger par un site malveillant qui inclue le site victime dans une iframe et superpose un autre contenu. L’utilisateur pense alors interagir avec le contenu d’un site alors qu’au final il est en train d’interagir avec le site victime caché en dessous.

Le site victime peut interdire aux navigateurs de l’encapsuler dans un autre en positionnant l’en-tête de sécurité X-Frame-Options à DENY (ou SAMEORIGIN pour un site qui utiliserait une iframe pour son fonctionnement).

Site inclu dans un autre site
Site inclu dans un autre site

Cross-Origin-Resource-Sharing (CORS)

Le CORS est un mécanisme de sécurité qui consiste à ajouter un ensemble d’en-têtes de sécurité contrôlant le partage de ressources entre deux “Origines” différentes. Je n’entre pas dans le détail de ce mécanisme, j’y consacrerai un article dédié.

Parmi les en-têtes CORS, Access-Control-Allow-Origin doit impérativement être présent pour le bon fonctionnement d’une API entre deux sous domaines (donc origines) différents. L’utilisation de la valeur * est à proscrire car elle ouvre les appels API à tous les sites externes.

Utilisation du CORS
Utilisation du CORS

Content-Security-Policy (CSP)

Nous venons de voir avec CORS qui peut accéder à nos ressources. L’en-tête CSP contrôle l’origine des ressources utilisées sur notre site. Entre autres, cette protection permet d’interdire l’exécution de scripts présents directement dans le code HTML de la page et donc de se prémunir contre une famille d’attaques de type Cross Site Scripting (XSS) les plus simples.

L’en-tête Content-Security-Policy est composé d’une liste de directives correspondant à chaque type de ressource (font, img, frame, …). Chaque directive déclare l’origine de la source des ressources. Le détail complet est présent sur la documentation de Mozilla.

Afin de construire un ensemble de directives robuste, il convient d’interdire par défaut l’ensemble des ressources (default-src 'none';) puis d’autoriser une à une les ressources (internes ou externes) à charger. Ce travail est plus facile lorsqu’il est réalisé dès la création du site web.

Des nombreux exemples sont fournis sur Internet pour comprendre ce fonctionnement :

Pour aider au déploiement, l’en-tête Content-Security-Policy-Report-Only permet d’expérimenter la CSP sans effectuer de blocage. Il ne faut pas oublier la directive report-uri pour recevoir un rapport lorsqu’une ressource contrevient aux règles de la CSP.

Utilisation des CSP
Utilisation des CSP

X-Content-Type-Options

Lorsque le navigateur demande une ressource, le serveur retourne le fichier demandé et, normalement, un en-tête Content-Type qui indique la nature du fichier. Lorsque l’en-tête n’est pas présent ou s’il ne correspond pas à ce qu’attend le navigateur, alors il peut mettre en place un mécanisme appelé MIME sniffing : il identifie le type de fichier suivant l’extension dans l’URL ou encore les premiers octets du fichiers (chaque navigateur a un heuristique propre). Lorsque l’en-tête X-Content-Type-Options a la valeur nosniff, le mécanisme n’est pas utilisé.

Pourquoi cela pose-t-il un problème ? Un site peut autoriser le chargement d’un fichier sur le serveur mais force ensuite un Content-Type lors du téléchargement du fichier. Un attaquant peut alors charger un certain fichier et réussir à l’ouvrir dans le navigateur de sa victime. Par exemple, un fichier texte contenant du code HTML est envoyé au site et l’URL de téléchargement est ensuite envoyée à la victime. Le navigateur de la victime va ouvrir et interpréter le fichier HTML alors qu’il aurait dû ne rien faire.

Referrer-Policy

L’en-tête Referer est inclus automatiquement à chaque requête HTTP du navigateur pour indiquer au serveur la page actuellement visitée. Le serveur connait ainsi la page qui demande une ressource.

Un serveur tiers héberge une feuille de style CSS. Lorsqu’elle est demandée (autorisée par les CSP) par le site victime, le serveur tiers web reçoit l’URL de la page. C’est ici qu’une fuite d’information peut avoir lieu. Si des secrets sont inclus dans l’URL, comme par exemple le jeton de réinitialisation du mot de passe, alors il sera envoyé à un site tiers. Ce dernier est alors en mesure de renouveler le mot de passe de l’utilisateur avant lui et lui voler son compte.

L’en-tête Referrer-Policy (avec deux r) indique au navigateur comment celui-ci doit se comporter avec l’en-tête Referer (avec un seul r). Plusieurs valeurs sont possibles, il convient de choisir la valeur adéquate pour limiter la fuite d’information sur des services tiers.

Referrer-Policy: no-referrer
Referrer-Policy: no-referrer-when-downgrade
Referrer-Policy: origin
Referrer-Policy: origin-when-cross-origin
Referrer-Policy: same-origin
Referrer-Policy: strict-origin
Referrer-Policy: strict-origin-when-cross-origin
Referrer-Policy: unsafe-url

La valeur unsafe-url n’est pas recommandée car elle positionne l’ensemble de l’URL (dont les paramètres) dans l’en-tête Referer. Un effort est apporté par les navigateurs pour ne plus inclure le chemin de l’URL dans l’en-tête. C’est le cas de Firefox depuis le version 87.

Fuite d&rsquo;information via l&rsquo;en-tête Referer
Fuite d’information via l’en-tête Referer

Cela peut surprendre mais j’ajoute l’en-tête Set-Cookie à cette liste parce qu’il permet lui aussi d’apporter de la sécurité. Lorsqu’un cookie est ajouté, plusieurs attributs sont à positionner :

  • Secure : interdit l’envoi du cookie dans les requêtes non sécurisées HTTP
  • HttpOnly : interdit l’accès à la valeur du cookie depuis du code Javascript
  • SameSite : contrôle l’envoi du cookie à certaines conditions

Pour un cookie de session (pas forcément pour un cookie applicatif), les attributs Secure et HttpOnly doivent impérativement être utilisés. L’attribut SameSite est souvent moins connu, il fera l’objet d’un article dédié.

X-XSS-Protection

Quand l’en-tête X-XSS-Protection est présent avec la valeur 1, le navigateur est invité à détecter les tentatives d’attaque de type Cross-Site-Scripting. Néanmoins, les chercheurs de vulnérabilités identifiée fréquement de nouvelles manières de contourner les filtres utilisés par cette protection.

Comme cela a été évoqué plus haut, l’en-tête CSP contrôle l’origine des scripts exécutés sur la page. Avec une valeur correctement positionnée, les vulnérabilités XSS les plus simples ne seront pas exécutées : l’attaquant devra aussi contourner la protection CSP.

Content-Security-Policy: script-src https://vimate.fr;

Forts de ce nouvel en-tête, les navigateurs modernes ne supportent plus l’en-tête X-XSS-Protection, il n’est donc plus recommandé de l’envoyer. Il est même indiqué par l’OWASP de spécifier la valeur à 0 ; le blocage du site devient un oracle permettant de déterminer si le site contient certaines informations.

D’autres en-têtes de sécurité

D’autres en-têtes existent pour contrôler la manière dont le navigateur doit se comporter avec les données du site. Ces en-têtes sont à positionner dans des cas particuliers :

Un exemple d’exploitation

Je mets à disposition un script Python sur un gist ici qui lance un serveur web avec différents exemples d’en-têtes de sécurité.

Implémenter les en-têtes dans son application

Les en-têtes HTTP peuvent être ajoutés par différents composants dans une application. En outre, dans certaines architectures, il peut y avoir plusieurs équipements entre un utilisateur et le code final. Par exemple :

  • La gateway exposée sur Internet ;
  • La terminaison SSL/TLS ;
  • Un Web Application Firewall (WAF) ;
  • Un load-balancer ;
  • Le framework utilisé ;
  • Le code qui gère la requête.

Il peut être alors difficile de savoir où positionner les en-têtes. Je vous propose ci-dessous des pistes de réflexion pour trouver le meilleur emplacement :

  • Strict-Transport-Security fait référence au HTTPS, il est recommandé de la positionner sur la terminaison SSL/TLS qui contrôle le chiffrement des flux avec l’utilisateur
  • Cross-Origin-Resource-Sharing et Content-Security-Policy sont deux en-têtes qui peuvent avoir des conséquences sur l’affichage du site, il est donc recommandé de les positionner au plus près du code pour les applications complexes
  • X-Frame-Options, X-Content-Type-Options et Referrer-Policy peuvent être positionnés sur les couches les plus proches de l’utilisateur
  • Pour Set-Cookie l’attribut HttpOnly peut être positionné par l’application mais l’attribut Secure sera placé par la terminaison SSL/TLS

Enfin, si un des en-têtes n’est pas présent, cela ne représente pas forcément une vulnérabilité. Chaque valeur doit être décidée dans le contexte de l’application. Par exemple, le CORS n’est pas obligatoire pour les pages HTML statiques et le CSP n’est pas obligatoire pour les API. Un cookie qui ne porte pas la session n’a pas forcément besoin d’avoir l’attribut httpOnly.

Synthèse

Voici un tableau reprenant les différents en-têtes. Les valeurs recommandées sont à adapter au contexte de chaque application.

Nom en-tête Valeur recommandée Lien documentation Mozilla
Strict-Transport-Security max-age=31536000 HTTP/Headers/Strict-Transport-Security
X-Frame-Options DENY HTTP/Headers/X-Frame-Options
Cross-Origin-Resource-Sharing Access-Control-Origin: https://domaine et autre en-têtes HTTP/CORS
Content-Security-Policy default-src 'none'; et autres directives HTTP/CSP
X-Content-Type-Options nosniff Headers/X-Content-Type-Options
Referrer-Policy no-referrer HTTP/Headers/Referrer-Policy
Set-Cookie Secure, httpOnly et SameSite=strict HTTP/Headers/Set-Cookie

Merci d'avoir lu cet article !

Si vous avez des commentaires ou des retours sur cet article, n'hésitez pas à me contacter. Venez aussi me dire bonjour sur Twitter ou sur Linkedin.