Protégez vos ressources contre les attaques sur le Web avec Fetch Metadata

Évitez les fuites d'informations CSRF, XSSI et d'informations multi-origines.

De nombreuses applications Web sont vulnérables aux attaques cross-origin, telles que la falsification de requête intersites (CSRF), l'inclusion de scripts intersites (XSSI), les attaques temporelles, les fuites d'informations multi-origines ou les attaques par canal auxiliaire d'exécution spéculative (Spectre).

Les en-têtes de requête Fetch Metadata vous permettent de déployer un mécanisme de défense en profondeur robuste (un règlement d'isolation des ressources) pour protéger votre application contre ces attaques multi-origines courantes.

Il est courant que les ressources exposées par une application Web donnée ne soient chargées que par l'application elle-même, et non par d'autres sites Web. Dans ce cas, déployer une règle d'isolation des ressources basée sur les en-têtes de requête Fetch Metadata demande peu d'efforts et, dans le même temps, protège l'application contre les attaques intersites.

Compatibilité du navigateur

Les en-têtes de requête Fetch Metadata sont compatibles avec tous les moteurs de navigateur modernes.

Navigateurs pris en charge

  • Chrome : 76.
  • Edge: 79
  • Firefox: 90
  • Safari : 16.4.

Source

Contexte

De nombreuses attaques intersites sont possibles, car le Web est ouvert par défaut et votre serveur d'applications ne peut pas facilement se protéger des communications provenant d'applications externes. Une attaque inter-origine typique est la falsification de requêtes intersites (CSRF, Cross-Site Request Forgery), où un pirate informatique attire un utilisateur sur un site qu'il contrôle, puis envoie un formulaire au serveur auquel l'utilisateur est connecté. Étant donné que le serveur ne peut pas déterminer si la requête provient d'un autre domaine (intersite) et que le navigateur associe automatiquement des cookies aux requêtes intersites, le serveur exécute l'action demandée par l'attaquant au nom de l'utilisateur.

D’autres attaques intersites telles que l’inclusion de script intersites (XSSI) ou les fuites d’informations multi-origines sont de nature similaire au CSRF et reposent sur le chargement de ressources à partir d’une application victime dans un document contrôlé par le pirate et la fuite d’informations sur les applications de la victime. Les applications ne pouvant pas distinguer facilement les requêtes approuvées de celles qui ne le sont pas, elles ne peuvent pas supprimer le trafic intersites malveillant.

Présentation de la récupération de métadonnées

Les en-têtes de requête Fetch Metadata sont une nouvelle fonctionnalité de sécurité de la plate-forme Web conçue pour aider les serveurs à se défendre contre les attaques inter-origines. En fournissant des informations sur le contexte d'une requête HTTP dans un ensemble d'en-têtes Sec-Fetch-*, elles permettent au serveur qui répond d'appliquer des règles de sécurité avant de traiter la requête. Cela permet aux développeurs d'accepter ou de rejeter une demande en fonction de la manière dont elle a été faite et du contexte dans lequel elle sera utilisée, ce qui permet de répondre uniquement aux demandes légitimes de leur propre application.

Same-Origin
Les requêtes provenant de sites hébergés par votre propre serveur (de même origine) continueront de fonctionner. Si vous envoyez une requête d'extraction depuis https://site.example pour la ressource https://site.example/foo.json en JavaScript, le navigateur envoie l'en-tête de requête HTTP "Sec Fetch-Site: same-origin".
Intersite
Les requêtes intersites malveillantes peuvent être rejetées par le serveur en raison du contexte supplémentaire fourni par les en-têtes Sec-Fetch-* dans la requête HTTP. Une image sur https://evil.example qui a défini l'attribut src d'un élément img sur "https://site.example/foo.json" entraîne l'envoi par le navigateur de l'en-tête de requête HTTP "Sec-Fetch-Site: cross-site".

Sec-Fetch-Site

Navigateurs pris en charge

  • Chrome: 76
  • Edge: 79
  • Firefox: 90
  • Safari : 16.4.

Source

Sec-Fetch-Site indique au serveur quel site a envoyé la requête. Le navigateur définit cette valeur sur l'une des valeurs suivantes:

  • same-origin, si la requête a été effectuée par votre propre application (par exemple, site.example)
  • same-site, si la demande a été effectuée par un sous-domaine de votre site (par exemple, bar.site.example)
  • none, si la requête a été explicitement déclenchée par l'interaction d'un utilisateur avec l'user-agent (par exemple, en cliquant sur un favori)
  • cross-site, si la requête a été envoyée par un autre site Web (par exemple, evil.example)

Sec-Fetch-Mode

Navigateurs pris en charge

  • Chrome: 76
  • Edge : 79.
  • Firefox : 90.
  • Safari : 16.4.

Source

Sec-Fetch-Mode indique le mode de la requête. Cela correspond approximativement au type de requête et vous permet de distinguer les charges de ressources des requêtes de navigation. Par exemple, une destination de navigate indique une requête de navigation de premier niveau, tandis que no-cors indique des requêtes de ressources telles que le chargement d'une image.

Sec-Fetch-Dest

Navigateurs pris en charge

  • Chrome : 80.
  • Edge : 80.
  • Firefox: 90
  • Safari : 16.4.

Source

Sec-Fetch-Dest expose la destination d'une requête (par exemple, si une balise script ou img a entraîné la demande d'une ressource par le navigateur).

Utiliser les métadonnées de récupération pour se protéger contre les attaques inter-origines

Les informations supplémentaires fournies par ces en-têtes de requête sont assez simples, mais le contexte supplémentaire vous permet de créer une logique de sécurité puissante côté serveur, également appelée règle d'isolation des ressources, avec seulement quelques lignes de code.

Implémenter une règle d'isolation des ressources

Une règle d'isolation des ressources empêche les sites Web externes de demander vos ressources. Le blocage de ce type de trafic réduit les failles Web intersites courantes telles que CSRF, XSSI, les attaques temporelles et les fuites d'informations multi-origines. Cette règle peut être activée pour tous les points de terminaison de votre application. Elle autorise toutes les requêtes de ressources provenant de votre propre application, ainsi que les navigations directes (via une requête HTTP GET). Vous pouvez désactiver cette logique pour les points de terminaison censés être chargés dans un contexte intersites (par exemple, les points de terminaison chargés à l'aide de CORS).

Étape 1 : Autorisez les requêtes des navigateurs qui n'envoient pas de métadonnées de récupération

Étant donné que tous les navigateurs ne sont pas compatibles avec la récupération de métadonnées, vous devez autoriser les requêtes qui ne définissent pas d'en-têtes Sec-Fetch-* en vérifiant la présence de sec-fetch-site.

if not req['sec-fetch-site']:
  return True  # Allow this request

Étape 2: Autorisez les requêtes lancées sur le même site ou par un navigateur

Toutes les requêtes qui ne proviennent pas d'un contexte inter-origine (comme evil.example) seront autorisées. Il s'agit en particulier de requêtes qui:

  • proviennent de votre propre application (par exemple, une requête de même origine où les requêtes site.example site.example/foo.json seront toujours autorisées).
  • proviennent de vos sous-domaines ;
  • sont explicitement causées par l'interaction d'un utilisateur avec l'agent utilisateur (par exemple, navigation directe ou clic sur un favori, etc.) ;
if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
  return True  # Allow this request

Étape 3 : Autoriser la navigation de premier niveau et l'iframing simples

Pour vous assurer que votre site peut toujours être associé à d'autres sites, vous devez autoriser la navigation de premier niveau simple (HTTP GET).

if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET'
  # <object> and <embed> send navigation requests, which we disallow.
  and req['sec-fetch-dest'] not in ('object', 'embed'):
    return True  # Allow this request

Étape 4 : Désactiver les points de terminaison destinés à diffuser du trafic intersites (facultatif)

Dans certains cas, votre application peut fournir des ressources destinées à être chargées entre les sites. Ces ressources doivent être exemptées pour chaque chemin d'accès ou point de terminaison. Exemples de points de terminaison de ce type:

  • Points de terminaison destinés à être accessibles entre origines : si votre application diffuse des points de terminaison CORS activés, vous devez les désactiver explicitement de l'isolation des ressources pour vous assurer que les requêtes intersites vers ces points de terminaison restent possibles.
  • Ressources publiques (images, styles, etc.): Toutes les ressources publiques et non authentifiées qui doivent être chargées inter-origines à partir d'autres sites peuvent également être exclues.
if req.path in ('/my_CORS_endpoint', '/favicon.png'):
  return True

Étape 5 : Refusez toutes les autres requêtes intersites qui ne sont pas liées à la navigation

Toute autre requête intersites sera refusée par cette règle d'isolation des ressources, ce qui protégera votre application contre les attaques intersites courantes.

Exemple : Le code suivant illustre une implémentation complète d'une règle d'isolation des ressources robuste sur le serveur ou en tant que middleware pour refuser les requêtes de ressources intersites potentiellement malveillantes, tout en autorisant les requêtes de navigation simples :

# Reject cross-origin requests to protect from CSRF, XSSI, and other bugs
def allow_request(req):
  # Allow requests from browsers which don't send Fetch Metadata
  if not req['sec-fetch-site']:
    return True

  # Allow same-site and browser-initiated requests
  if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
    return True

  # Allow simple top-level navigations except <object> and <embed>
  if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET'
    and req['sec-fetch-dest'] not in ('object', 'embed'):
      return True

  # [OPTIONAL] Exempt paths/endpoints meant to be served cross-origin.
  if req.path in ('/my_CORS_endpoint', '/favicon.png'):
    return True

  # Reject all other requests that are cross-site and not navigational
  return False

Déployer une règle d'isolation de ressources

  1. Installez un module tel que l'extrait de code ci-dessus pour consigner et surveiller le comportement de votre site, et vous assurer que les restrictions n'affectent pas le trafic légitime.
  2. Résolvez les cas de non-respect potentiels en excluant les points de terminaison inter-origine légitimes.
  3. Appliquez la règle en abandonnant les requêtes non conformes.

Identifier et corriger les cas de non-respect des règles

Nous vous recommandons de tester votre stratégie sans effets secondaires en l'activant d'abord en mode de création de rapports dans votre code côté serveur. Vous pouvez également implémenter cette logique dans un middleware ou dans un proxy inverse qui consigne toutes les infractions que votre règle peut générer lorsqu'elle est appliquée au trafic de production.

D'après notre expérience de déploiement d'une règle d'isolation des ressources de récupération des métadonnées chez Google, la plupart des applications sont compatibles par défaut avec ce type de règle et nécessitent rarement des points de terminaison exemptés pour autoriser le trafic intersites.

Appliquer une règle d'isolation des ressources

Après avoir vérifié que vos règles n'ont aucune incidence sur le trafic de production légitime, vous pouvez appliquer des restrictions afin de garantir que les autres sites ne pourront pas demander vos ressources et de protéger vos utilisateurs contre les attaques intersites.

Documentation complémentaire