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

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

Pourquoi est-il important d'isoler vos ressources Web ?

De nombreuses applications Web sont vulnérables aux attaques multi-origines telles que la falsification des requêtes intersites (CSRF), l'inclusion de scripts intersites (XSSI), les attaques par synchronisation, 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 (Extraire les métadonnées) vous permettent de déployer un mécanisme de défense en profondeur performant (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 de tels cas, le déploiement d'une règle d'isolation des ressources basée sur des en-têtes de requête de récupération de métadonnées demande peu d'efforts et protège l'application contre les attaques intersites.

Compatibilité du navigateur

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

Navigateurs pris en charge

  • 76
  • 79
  • 90
  • 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 se protéger facilement contre les communications émanant d'applications externes. Une attaque multi-origine typique est la falsification de requête intersites (CSRF) : 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 (intersites) et que le navigateur associe automatiquement des cookies aux requêtes intersites, le serveur exécute l'action demandée par le pirate informatique au nom de l'utilisateur.

D'autres attaques intersites, telles que l'inclusion de scripts intersites (XSSI) ou les fuites d'informations multi-origines, sont similaires par leur nature à celles de CSRF. Elles reposent sur le chargement des ressources d'une application victime dans un document contrôlé par l'attaquant et la fuite d'informations sur les applications victimes. Dans la mesure où les applications ne peuvent pas distinguer facilement les requêtes fiables de celles qui ne le sont pas, elles ne peuvent pas supprimer le trafic malveillant intersites.

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

Les en-têtes de requêtes Fetch Metadata sont une nouvelle fonctionnalité de sécurité des plates-formes Web conçue pour aider les serveurs à se défendre contre les attaques multi-origines. En fournissant des informations sur le contexte d'une requête HTTP dans un ensemble d'en-têtes Sec-Fetch-*, ils permettent au serveur qui répond d'appliquer des règles de sécurité avant de traiter la requête. Les développeurs peuvent ainsi choisir d'accepter ou de refuser une demande en fonction de la manière dont elle a été effectuée et du contexte dans lequel elle sera utilisée. Ils peuvent ainsi répondre uniquement aux requêtes légitimes émises par leur propre application.

Même origine
Les requêtes provenant de sites diffusés par votre propre serveur (même origine) continueront de fonctionner. Une requête de récupération de https://site.example pour la ressource https://site.example/foo.json dans JavaScript entraîne l'envoi par le navigateur de l'en-tête de requête HTTP "Sec Fetch-Site: same-origin".
Inter-sites
Les requêtes intersites malveillantes peuvent être rejetées par le serveur en raison du contexte supplémentaire fourni par la requête HTTP par les en-têtes Sec-Fetch-*. Sur la page https://evil.example, lorsque l'attribut src d'un élément img est défini sur "https://site.example/foo.json", le navigateur envoie l'en-tête de requête HTTP "Sec-Fetch-Site: cross-site".

Sec-Fetch-Site

Navigateurs pris en charge

  • 76
  • 79
  • 90
  • 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 causée par l'interaction d'un utilisateur avec le user-agent (par exemple, un clic 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

  • 76
  • 79
  • 90
  • 16.4

Source

Sec-Fetch-Mode indique le mode de la requête. Cela correspond à peu près 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

  • 80
  • 80
  • 90
  • 16.4

Source

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

Utiliser l'API Fetch Metadata pour vous protéger contre les attaques multi-origines

Les informations supplémentaires fournies par ces en-têtes de requêtes 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.

Mettre en œuvre une règle d'isolation de ressources

Une règle d'isolation des ressources empêche les demandes de vos ressources par des sites Web externes. Le blocage de ce type de trafic atténue les failles Web courantes intersites 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 demandes 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 provenant de navigateurs qui n'envoient pas l'API Fetch Metadata

Étant donné que tous les navigateurs ne sont pas compatibles avec la récupération des 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 et celles déclenchées par le navigateur

Toutes les requêtes ne provenant pas d'un contexte multi-origine (comme evil.example) seront autorisées. Il s'agit notamment des requêtes suivantes:

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

Étape 3: Autorisez la navigation de premier niveau simple et les cadres iFrame

Pour vous assurer que votre site peut toujours être accessible depuis d'autres sites, vous devez autoriser une 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ésactivez les points de terminaison destinés à diffuser le trafic intersite (facultatif)

Dans certains cas, votre application peut fournir des ressources destinées à être chargées entre les sites. Ces ressources doivent être exemptées par chemin ou par point de terminaison. Voici quelques exemples de points de terminaison de ce type:

  • Points de terminaison conçus pour être accessibles en multi-origine: si votre application diffuse des points de terminaison sur lesquels CORS est activé, vous devez explicitement les désactiver de l'isolation des ressources pour vous assurer que les requêtes intersites adressées à ces points de terminaison restent possibles.
  • Ressources publiques (par exemple, images, styles, etc.): Les ressources publiques et non authentifiées qui devraient pouvoir être chargées en multi-origine depuis d'autres sites peuvent également être exemptées.
if req.path in ('/my_CORS_endpoint', '/favicon.png'):
  return True

Étape 5: Refusez toutes les autres demandes intersites et ne concernant pas la navigation

Toute autre requête intersite sera rejetée par cette règle d'isolation des ressources, protégeant ainsi votre application contre les attaques intersites courantes.

Exemple:Le code suivant illustre l'implémentation complète d'une règle d'isolation des ressources fiable sur le serveur ou en tant que middleware afin de 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 aucun trafic légitime.
  2. Corrigez les cas de non-respect potentiels en excluant les points de terminaison multi-origines 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 règle sans aucun effet secondaire 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 tous les cas de non-respect susceptibles d'être générés par votre règle lorsqu'elle est appliquée au trafic de production.

D'après notre expérience du 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 d'exempter des points de terminaison pour autoriser le trafic intersites.

Appliquer une règle d'isolation de ressources

Après avoir vérifié que vos règles n'ont aucun impact 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.

Complément d'informations