Renforcement de la sécurité et de la confidentialité grâce au partitionnement du cache

En général, la mise en cache peut améliorer les performances en stockant des données afin que les futures requêtes portant sur les mêmes données soient diffusées plus rapidement. Par exemple, une ressource mise en cache depuis le réseau peut éviter un aller-retour vers le serveur. Un résultat de calcul mis en cache peut omettre le temps nécessaire pour effectuer le même calcul.

Dans Chrome, le mécanisme de cache est utilisé de différentes manières, dont le cache HTTP.

Fonctionnement actuel du cache HTTP de Chrome

Depuis la version 85, Chrome met en cache les ressources récupérées sur le réseau en utilisant leurs URL de ressources respectives comme clé de cache. (Une clé de cache permet d'identifier une ressource mise en cache.)

L'exemple suivant montre comment une seule image est mise en cache et traitée dans trois contextes différents:

Clé de cache: https://x.example/doge.png
Clé de cache: { https://x.example/doge.png }

Un utilisateur consulte une page (https://a.example) qui demande une image (https://x.example/doge.png). L'image est demandée au réseau et mise en cache à l'aide de https://x.example/doge.png comme clé.

Clé de cache: https://x.example/doge.png
Clé de cache: { https://x.example/doge.png }

Le même utilisateur visite une autre page (https://b.example), qui demande la même image (https://x.example/doge.png). Le navigateur vérifie son cache HTTP pour voir s'il a déjà mis en cache cette ressource, en utilisant l'URL de l'image comme clé. Le navigateur trouve une correspondance dans son cache et utilise donc la version mise en cache de la ressource.

Clé de cache: https://x.example/doge.png
Clé de cache: { https://x.example/doge.png }

Peu importe si l'image est chargée depuis un iFrame. Si l'utilisateur visite un autre site Web (https://c.example) avec un iFrame (https://d.example) et que cet iFrame demande la même image (https://x.example/doge.png), le navigateur peut quand même charger l'image à partir de son cache, car la clé de cache est la même sur toutes les pages.

Ce mécanisme fonctionne bien du point de vue des performances depuis longtemps. Toutefois, le temps nécessaire pour qu'un site Web réponde aux requêtes HTTP peut révéler que le navigateur a déjà accédé à la même ressource par le passé, ce qui expose le navigateur à des attaques liées à la sécurité et à la confidentialité, comme celles indiquées ci-dessous:

  • Détecter si un utilisateur a visité un site spécifique: un attaquant peut détecter l'historique de navigation d'un utilisateur en vérifiant si le cache contient une ressource potentiellement spécifique à un site particulier ou à une cohorte de sites.
  • Attaque par recherche intersites : un attaquant peut détecter la présence d'une chaîne arbitraire dans les résultats de recherche de l 'utilisateur en vérifiant si une image "aucun résultat de recherche" utilisée par un site Web particulier se trouve dans le cache du navigateur.
  • Suivi intersites: le cache peut être utilisé pour stocker des identifiants de type cookie en tant que mécanisme de suivi intersites.

Pour limiter ces risques, Chrome partitionnera son cache HTTP à partir de Chrome 86.

Comment le partitionnement du cache affecte-t-il le cache HTTP de Chrome ?

Avec le partitionnement du cache, les ressources mises en cache seront associées à une nouvelle "clé d'isolation réseau" en plus de l'URL de la ressource. La clé d'isolation réseau se compose du site de premier niveau et du site du cadre actuel.

Examinez à nouveau l'exemple précédent pour voir comment fonctionne le partitionnement du cache dans différents contextes:

Clé de cache { https://a.example, https://a.example, https://x.example/doge.png}
Clé de cache: { https://a.example, https://a.example, https://x.example/doge.png }

Un utilisateur visite une page (https://a.example) qui demande une image (https://x.example/doge.png). Dans ce cas, l'image est demandée au réseau et mise en cache à l'aide d'un tuple composé de https://a.example (le site de premier niveau), de https://a.example (le site utilisant le cadre actuel) et de https://x.example/doge.png (l'URL de la ressource) comme clé. (Notez que lorsque la demande de ressource provient du frame de premier niveau, le site de premier niveau et le site du frame actuel dans la clé d'isolation réseau sont identiques.)

Clé de cache { https://a.example, https://a.example, https://x.example/doge.png}
Clé de cache: { https://b.example, https://b.example, https://x.example/doge.png }

Le même utilisateur visite une autre page (https://b.example) qui demande la même image (https://x.example/doge.png). Bien que la même image ait été chargée dans l'exemple précédent, comme la clé ne correspond pas, il ne s'agit pas d'un succès de cache.

L'image est demandée à partir du réseau et mise en cache à l'aide d'un tuple composé de https://b.example, https://b.example et https://x.example/doge.png comme clé.

Clé de cache { https://a.example, https://a.example, https://x.example/doge.png}
Clé de cache: { https://a.example, https://a.example, https://x.example/doge.png }

L'utilisateur revient maintenant à https://a.example, mais cette fois, l'image (https://x.example/doge.png) est intégrée dans un iFrame. Dans ce cas, la clé est un tuple contenant https://a.example, https://a.example et https://x.example/doge.png, et un succès de cache se produit. Notez que lorsque le site de premier niveau et l'iFrame sont le même site, la ressource mise en cache avec le frame de premier niveau peut être utilisée.

Clé de cache { https://a.example, https://a.example, https://x.example/doge.png}
Clé de cache: { https://a.example, https://c.example, https://x.example/doge.png }

L'utilisateur est de retour à https://a.example, mais cette fois l'image est hébergée dans un iFrame depuis https://c.example.

Dans ce cas, l'image est téléchargée à partir du réseau, car aucune ressource dans le cache ne correspond à la clé composée de https://a.example, https://c.example et https://x.example/doge.png.

Clé de cache { https://a.example, https://a.example, https://x.example/doge.png}
Clé de cache: { https://a.example, https://c.example, https://x.example/doge.png }

Que se passe-t-il si le domaine contient un sous-domaine ou un numéro de port ? L'utilisateur consulte https://subdomain.a.example, qui intègre un iFrame (https://c.example:8080), qui demande l'image.

Étant donné que la clé est créée sur la base "scheme://eTLD+1", les sous-domaines et les numéros de port sont ignorés. Par conséquent, un succès de cache se produit.

Clé de cache { https://a.example, https://a.example, https://x.example/doge.png}
Clé de cache: { https://a.example, https://c.example, https://x.example/doge.png }

Que se passe-t-il si l'iFrame est imbriqué plusieurs fois ? L'utilisateur consulte https://a.example, qui intègre un iFrame (https://b.example), qui intègre encore un autre iFrame (https://c.example), qui demande finalement l'image.

Étant donné que la clé provient du cadre supérieur (https://a.example) et du cadre immédiat qui charge la ressource (https://c.example), un succès de cache se produit.

Questions fréquentes

Est-il déjà activé sur mon navigateur Chrome ? Comment vérifier ?

Cette fonctionnalité sera déployée fin 2020. Pour vérifier si votre instance Chrome est déjà compatible:

  1. Ouvrez chrome://net-export/ et appuyez sur Débuter la journalisation sur le disque.
  2. Indiquez l'emplacement d'enregistrement du fichier journal sur votre ordinateur.
  3. Parcourez le Web sur Chrome pendant une minute.
  4. Revenez à chrome://net-export/ et appuyez sur Arrêter la journalisation.
  5. Allez sur https://netlog-viewer.appspot.com/#import.
  6. Appuyez sur Choose File (Sélectionner un fichier) et transmettez le fichier journal que vous avez enregistré.

La sortie du fichier journal s'affiche.

Sur la même page, recherchez SplitCacheByNetworkIsolationKey. S'il est suivi de Experiment_[****], le partitionnement du cache HTTP est activé sur votre Chrome. Si elle est suivie de Control_[****] ou Default_[****], elle n'est pas activée.

Comment puis-je tester le partitionnement du cache HTTP sur mon navigateur Chrome ?

Pour tester le partitionnement du cache HTTP dans Chrome, vous devez lancer Chrome avec l'indicateur de ligne de commande --enable-features=SplitCacheByNetworkIsolationKey. Pour savoir comment lancer Chrome avec un indicateur de ligne de commande sur votre plate-forme, suivez les instructions de la section Exécuter Chromium avec des indicateurs.

En tant que développeur Web, dois-je prendre des mesures en réponse à ce changement ?

Il ne s'agit pas d'une modification destructive, mais elle peut imposer des considérations de performances pour certains services Web.

Par exemple, ceux qui diffusent d'importants volumes de ressources pouvant être mises en cache sur de nombreux sites (comme les polices et les scripts populaires) peuvent constater une augmentation de leur trafic. En outre, les utilisateurs de ces services peuvent être davantage dépendants d'eux.

(Il existe une proposition d'activer les bibliothèques partagées tout en protégeant la confidentialité : les bibliothèques partagées Web (vidéo de présentation), mais elle est toujours à l'étude.

Quel est l'impact de ce changement de comportement ?

Le taux global de défaut de cache (miss) augmente d'environ 3,6%, les modifications apportées au FCP (First Contentful Paint) sont mineures (~0,3%) et la fraction globale d'octets chargés à partir du réseau augmente d'environ 4%. Pour en savoir plus sur l'impact sur les performances, consultez la présentation du partitionnement du cache HTTP.

Est-ce standardisé ? Les autres navigateurs se comportent-ils différemment ?

La mention "Partitions de cache HTTP" est normalisée dans les spécifications de récupération, même si les navigateurs se comportent différemment:

  • Chrome: utilise l'extension schema://eTLD+1 de premier niveau et le schéma de cadre://eTLD+1.
  • Safari: utilise l'eTLD+1 de premier niveau.
  • Firefox: mise en œuvre planifiée avec l'adresse schema://eTLD+1 de premier niveau et envisage d'inclure une deuxième clé, comme Chrome.

Comment l'extraction à partir des nœuds de calcul est-elle traitée ?

Les nœuds de calcul dédiés utilisent la même clé que leur frame actuel. Les service workers et les workers partagés sont plus compliqués, car ils peuvent être partagés entre plusieurs sites de premier niveau. La solution à leur offrir est en cours de discussion.

Ressources