Nous avons découvert un identifiant Firefox stable qui relie toutes les identités Tor privées d’un utilisateur
(fingerprint.com)- Le seul ordre de retour de
indexedDB.databases()permet de générer, dans les navigateurs basés sur Firefox, un identifiant stable qui persiste pendant toute la durée de vie du processus - Cet identifiant est partagé au-delà du périmètre d’origine, si bien que des sites sans lien entre eux peuvent observer la même valeur dans un même runtime du navigateur et l’exploiter pour du suivi cross-origin
- Dans le mode de navigation privée de Firefox, l’identifiant persiste tant que le processus reste actif, même après la fermeture de toutes les fenêtres privées, et il continue aussi d’exister après New Identity dans Tor Browser
- La cause se trouve dans l’implémentation IndexedDB de Gecko, qui mappe les noms de bases de données privées vers des noms de fichiers fondés sur des UUID et expose ensuite le résultat sans tri
- Mozilla a déployé un correctif dans Firefox 150 et ESR 140.10.0 ; il est crucial, pour protéger la vie privée, que la conception n’expose pas vers l’extérieur l’ordre du stockage interne
Vue d’ensemble de la vulnérabilité
- Dans tous les navigateurs basés sur Firefox, il est possible d’extraire un identifiant persistant pendant la durée de vie du processus à partir de l’ordre des éléments renvoyés par
indexedDB.databases()- En créant plusieurs bases IndexedDB puis en observant l’ordre de retour, un site web peut produire un identifiant unique et déterministe du processus de navigateur en cours d’exécution
- Ce comportement apparaît à l’échelle du processus, et non de l’origine ; des sites sans rapport peuvent donc observer le même identifiant dans un même runtime du navigateur
- Dans le mode de navigation privée de Firefox, l’identifiant persiste tant que le processus Firefox continue de tourner, même après la fermeture de toutes les fenêtres privées
- Dans Tor Browser, cet identifiant stable subsiste même après New Identity, qui est censé effacer les cookies et l’historique puis utiliser un nouveau circuit Tor
- Cela entre en conflit avec l’attente selon laquelle l’activité ultérieure ne devrait pas pouvoir être reliée à l’activité précédente, et affaiblit la garantie de non-corrélation sur laquelle s’appuient les utilisateurs
- Une divulgation responsable a été menée auprès de Mozilla et du Tor Project
- Mozilla a publié un correctif dans Firefox 150 et ESR 140.10.0
- Le correctif est suivi dans Mozilla Bug 2024220 ; la cause se situe dans l’implémentation IndexedDB de Gecko et concerne donc aussi Tor Browser et d’autres navigateurs basés sur Firefox
- Le principe du correctif est simple
- Le navigateur ne doit pas exposer à l’extérieur l’ordre du stockage interne à l’échelle du processus
- Normaliser ou trier les résultats avant de les renvoyer permet de supprimer cette source d’entropie et d’empêcher son exploitation comme identifiant stable
Pourquoi c’est important
- Le mode de navigation privée et les navigateurs centrés sur la protection de la vie privée ont pour objectif de rendre plus difficile l’identification d’un utilisateur dans différents contextes
- Attente générale 1 : en l’absence de stockage partagé ou de mécanisme d’identité explicite, des sites sans lien ne devraient pas pouvoir savoir s’ils interagissent avec la même instance du navigateur
- Attente générale 2 : lorsqu’une session privée se termine, les informations qui lui sont associées devraient disparaître elles aussi
- Ce comportement brise ces deux attentes
- Un site peut dériver un identifiant uniquement à partir du fonctionnement interne du stockage du navigateur, sans cookies, sans localStorage et sans canal cross-site explicite
- L’ordre des noms de bases de données renvoyé par l’API fournit un signal d’identification à forte capacité
- Il y a aussi une leçon côté développement
- Les vulnérabilités de confidentialité ne viennent pas uniquement d’un accès direct à des données identifiantes
- Elles peuvent aussi résulter de la divulgation déterministe de détails d’implémentation internes
- Le point clé, côté sécurité produit
- Même une API en apparence anodine peut devenir un vecteur de suivi intersites si elle fuit un état stable au niveau du processus
IndexedDB et indexedDB.databases()
- IndexedDB est une API navigateur de stockage structuré côté client
- Les applications web l’utilisent pour le mode hors ligne, le cache, l’état de session et d’autres besoins de stockage local
- Chaque origine peut créer une ou plusieurs bases de données nommées, avec des object stores et de grands volumes de données
indexedDB.databases()renvoie les métadonnées des bases visibles pour l’origine courante- Les développeurs peuvent l’utiliser pour vérifier les bases existantes, déboguer l’usage du stockage ou gérer l’état d’une application
- Dans un modèle normal de protection de la vie privée, l’ordre de retour de cette API ne devrait pas, à lui seul, contenir d’information identifiante
- Il faudrait une représentation neutre ou normalisée des métadonnées de base de données
- Le vrai problème est que, dans les navigateurs basés sur Firefox, l’ordre de retour était loin d’être neutre
Comment indexedDB.databases() est devenu un identifiant stable
- En navigation privée sous Firefox,
indexedDB.databases()renvoie les métadonnées dans un ordre dérivé de la structure de stockage interne, et non dans l’ordre de création des bases- L’implémentation concernée se trouve dans
dom/indexedDB/ActorsParent.cpp
- L’implémentation concernée se trouve dans
- En navigation privée, les noms de base ne sont pas utilisés directement comme identifiants disque
- À la place, ils sont mappés vers une base de nom de fichier fondée sur un UUID via la table de hachage globale
StorageDatabaseNameHashtable = nsTHashMap<nsString, nsString> - Ce mapping est réalisé dans
GetDatabaseFilenameBase()à l’intérieur deOpenDatabaseOp::DoDatabaseWork()
- À la place, ils sont mappés vers une base de nom de fichier fondée sur un UUID via la table de hachage globale
- Quand
aIsPrivatevaut true, le nom de base fourni par le site est remplacé par un UUID généré puis stocké dans la table globaleStorageDatabaseNameHashtable- La clé utilise uniquement la chaîne du nom de base de données
- Le mapping persiste pendant toute la durée de vie du QuotaClient d’IndexedDB
- Il est partagé entre toutes les origines
- Il n’est réinitialisé qu’au redémarrage complet de Firefox
- Lors d’un appel ultérieur à
indexedDB.databases(), Firefox collecte les noms de fichiers des bases viaQuotaClient::GetDatabaseFilenames(...)depuisGetDatabasesOp::DoDatabaseWork()- Les noms de base sont insérés dans un
nsTHashSet - Aucun tri n’est effectué avant l’itération
- Les noms de base sont insérés dans un
- L’ordre final des résultats est déterminé par le parcours de la disposition interne des buckets du hash set
- Comme le mapping UUID reste stable pendant toute la durée de vie du processus Firefox, l’ordre de retour reste lui aussi une fonction déterministe des UUID générés, du comportement de la fonction de hachage, de la capacité de la table et de l’historique d’insertion
- Cet ordre persiste d’un onglet à l’autre et d’une fenêtre privée à l’autre, et n’est réinitialisé qu’au redémarrage complet du navigateur
- Le mapping UUID comme le parcours du hash set relèvent du périmètre du processus, et non de celui de l’origine
Méthode de reproduction
- Un PoC simple suffit à démontrer le comportement
- Deux origines différentes hébergent le même script
- Chaque script crée un ensemble fixe de bases, appelle
indexedDB.databases(), extrait l’ordre de retour et l’affiche
- Dans les builds affectés de Firefox en navigation privée et de Tor Browser, les deux origines observent la même permutation pendant toute la durée de vie du même processus navigateur
- La permutation change au redémarrage du navigateur
- Exemple de sortie conceptuelle
- Ordre de création :
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p - Ordre de retour :
g,c,p,a,l,f,n,d,j,b,o,h,e,m,i,k
- Ordre de création :
- Le point essentiel n’est pas la séquence exacte
- Elle diffère de l’ordre de création initial
- Le même ordre apparaît sur des origines sans lien entre elles
- Il persiste après un rechargement, dans une nouvelle fenêtre privée, et même après fermeture de toutes les fenêtres privées
- Un nouvel ordre n’est généré qu’après redémarrage complet du navigateur
- Cela permet de vérifier directement une propriété indésirable du point de vue de la confidentialité
Impact sur la vie privée
- Cette vulnérabilité permet à la fois un suivi cross-origin et un suivi same-origin au sein d’un même runtime du navigateur
-
Impact cross-origin
- Des sites sans lien peuvent dériver indépendamment le même identifiant et en déduire qu’ils interagissent avec le même processus Firefox ou Tor Browser en cours d’exécution
- Cela permet de corréler l’activité entre domaines sans cookies ni autre stockage partagé
-
Impact same-origin
- Dans la navigation privée de Firefox, l’identifiant persiste tant que le processus Firefox continue de tourner, même après la fermeture de toutes les fenêtres privées
- Un site peut donc reconnaître une visite ultérieure qui semble pourtant appartenir à une nouvelle session privée
- Dans Tor Browser, l’identifiant stable neutralise de fait l’isolation fournie par New Identity tant que le même processus navigateur reste actif
- Il autorise un lien entre des sessions qui devraient être totalement séparées
-
Pourquoi c’est particulièrement grave dans Tor Browser
- Tor Browser est conçu pour réduire les possibilités de corrélation intersites et minimiser l’identification au niveau de l’instance du navigateur
- Un identifiant stable qui persiste pendant la durée de vie du processus entre directement en contradiction avec cet objectif de conception
- Même s’il ne survit pas à un redémarrage complet, cela suffit à affaiblir significativement la non-corrélation lors d’un usage actif
Entropie et capacité de fingerprinting
- Ce signal n’est pas seulement stable, il a aussi une forte capacité
- Si un site contrôle
Nnoms de base de données, le nombre de permutations observables estN! - L’entropie théorique est
log2(N!)
- Si un site contrôle
- Avec 16 noms contrôlables, l’espace théorique atteint environ 44 bits
- C’est suffisant pour distinguer les instances simultanées de navigateur dans des conditions réelles
- Le nombre réel de permutations atteignables peut être un peu plus faible en raison du fonctionnement interne de la table de hachage
- Mais cela ne change pas le point essentiel du point de vue sécurité
- L’ordre exposé fournit toujours assez d’entropie pour agir comme un identifiant fort
Comment corriger
- Le bon correctif consiste à cesser d’exposer l’entropie dérivée de la disposition interne du stockage
- La mesure la plus propre est de renvoyer les résultats dans un ordre canonique, par exemple un tri lexicographique
- Cela préserve l’utilité de l’API pour les développeurs tout en supprimant le signal de fingerprinting
- Une randomisation de la sortie à chaque appel pourrait aussi masquer un ordre stable
- Mais le tri est une option plus simple, plus prévisible et plus facile à comprendre pour les développeurs
- Conditions d’un correctif idéal du point de vue de l’ingénierie sécurité
- Faible complexité conceptuelle
- Risque minimal de compatibilité
- Suppression directe de la fuite de confidentialité
Divulgation responsable
- Une divulgation responsable a été menée auprès de Mozilla et du Tor Project
- Mozilla a déployé un correctif dans Firefox 150 et ESR 140.10.0
- Le patch est suivi dans Mozilla Bug 2024220
- L’origine du comportement se trouve dans l’implémentation IndexedDB de Gecko
- Les navigateurs dérivés de Gecko, dont Tor Browser, sont donc concernés s’ils n’ont pas leur propre mesure d’atténuation
Conception orientée confidentialité
- Même de petits détails d’implémentation peuvent déboucher sur de vrais problèmes de confidentialité
- Des sites sans lien peuvent corréler l’activité au-delà des origines pendant un même runtime du navigateur
- L’identifiant persiste plus longtemps que ne l’attend l’utilisateur, ce qui affaiblit les frontières entre sessions privées
- Le point positif est que la correction est simple et efficace
- Normaliser la sortie avant de la renvoyer permet d’éliminer cette source d’entropie
- Les frontières de confidentialité attendues peuvent ainsi être restaurées
- Il s’agit d’un type de vulnérabilité facile à manquer, mais à fort impact, qui mérite une attention particulière lors de la conception de fonctionnalités sensibles à la vie privée
1 commentaires
Commentaires Hacker News
J’ai trouvé cette recherche vraiment impressionnante, et l’article est très bien écrit
Je m’attendais à voir une pub produit à la fin, et j’ai plutôt été surpris qu’il n’y en ait pas
En revanche, si cette entreprise fait du fingerprinting avec son produit, je me demande pourquoi elle a signalé cette vulnérabilité à Mozilla
Même si c’est contraire à l’éthique, la garder privée n’aurait-elle pas été plus intéressante commercialement pour se différencier de la concurrence ?
On voit rarement des acteurs malveillants griller leurs propres zero-day via une divulgation responsable
Comme l’explique l’article, l’identifiant peut persister tant que le processus Firefox reste en vie, donc avec Tor Browser il faut absolument quitter complètement le navigateur à la fin d’une session
Il est aussi important de ne pas mélanger des usages différents au sein d’une même session
Le lien posté par l’OP expirait dans mon environnement Tor, mais la version Wayback s’ouvrait sans problème
Et je me demande aussi s’il existe des chercheurs universitaires qui travaillent sur ce sujet
Je connais les actions d’organisations comme l’EFF, mais je cherche plutôt des professeurs d’université ou des laboratoires de recherche pure comme MSR ou PARC que des militants d’ONG
En tant que personne très sensible à la vie privée, j’ai l’impression qu’avec ma sainte trinité personnelle — noscript, ublock origin et firefox containers — je peux assez bien renforcer la sécurité, mais que l’anonymat m’échappe sans cesse à cause du fingerprinting
Et si on inclut aussi la stylométrie dans le fingerprinting au sens large, c’est encore plus vrai
Regarder des conférences comme PETS peut être utile
Je me demande déjà comment un site web peut accéder à ce genre d’informations sans même les demander à l’utilisateur ni l’en informer
Je me demande pourquoi les navigateurs ne sont pas conçus comme les téléphones, avec une demande d’autorisation quand un serveur ou une app veut accéder à ce type d’informations
Le user agent qui indique la version du navigateur est raisonnablement légitime, et demander quelles polices sont installées sur le système est difficile à supprimer totalement à cause du support typographique
Le fuseau horaire, la langue, la disposition du clavier, la taille de l’écran et celle de la fenêtre sont aussi nécessaires au fonctionnement normal du web
Il est également logique qu’un lecteur vidéo ou audio ait besoin de savoir quels formats sont pris en charge afin de servir le bon média
Tant que JavaScript peut lire l’heure, il est aussi facile d’estimer la dérive de l’horloge système en la comparant à l’heure du serveur
Et à mesure qu’on additionne tous ces éléments, presque tous les navigateurs finissent par devenir identifiables de manière unique
Et cette même entreprise finance en grande partie son plus gros concurrent
Donc je ne trouve pas cette réalité si surprenante
Les apps ont accès à bien plus d’identifiants et de caractéristiques matérielles
Même sur des systèmes relativement bien protégés sans Google Play services
À l’inverse, côté Apple, je trouve dommage qu’il y ait si peu de contrôle fin
Les navigateurs ont déjà une complexité comparable à celle d’un OS, donc presque n’importe quelle partie du système peut être exposée involontairement et exploitée
L’expression process-scoped utilisée dans l’article m’a un peu embrouillé
Je me souvenais que Mozilla avait présenté en 2021 un mode expérimental one-process-per-site pour Firefox, en expliquant que Firefox Desktop établirait des frontières au niveau des processus système entre tous les sites
L’article concerné est Introducing Site Isolation in Firefox
Du coup, je me demande si cette fonctionnalité n’a toujours pas été entièrement déployée, ou si elle l’a été mais qu’IndexedDB se trouve en dehors de cette isolation
Si c’est bien cela, je trouve l’explication assez intéressante
D’après cette explication, on dirait que cela ne persiste pas après un redémarrage du navigateur ; dans ce cas, du point de vue de l’attaquant, l’utilité ne baisse-t-elle pas fortement ?
En navigation privée de Firefox, l’identifiant peut persister même après la fermeture de toutes les fenêtres privées tant que le processus Firefox continue de tourner
Et dans Tor Browser, j’en comprends que même New Identity — censé faire une remise à zéro complète en effaçant les cookies et l’historique puis en utilisant un nouveau circuit Tor — laisse subsister cet identifiant stable
D’abord, le site fingerprint le navigateur et stocke dans un cookie un ID et l’empreinte
Lors de la session suivante, il refait le fingerprinting et compare avec le cookie ; si la valeur a changé, il envoie au serveur l’ancienne et la nouvelle empreinte afin de les relier
Les agences étatiques peuvent probablement déjà connaître ou suivre un grand nombre de nœuds, et en recoupant plusieurs métadonnées, on peut identifier quelqu’un avec une assez bonne précision
Il n’est pas nécessaire d’avoir une précision de 100 %, et on peut aussi accumuler beaucoup d’informations indirectes, comme des données sur la zone alentour ou obtenues à travers un mur, plutôt que sur la cible elle-même
Je vois cela comme une forme d’identification par informations proxy
Franchement, une bonne partie des Web Standards semblent davantage servir au fingerprinting qu’à des fonctionnalités réelles
J’ai l’impression que peu de sites utilisent réellement IndexedDB comme stockage, et je me demande qui en a vraiment besoin
C’est pourquoi je pense que la direction consistant à étendre sans cesse les standards du web est elle-même une erreur
Les navigateurs ne devraient fournir qu’un minimum d’API pour interagir avec l’appareil, et des fonctionnalités comme IndexedDB pourraient être implémentées sous forme de bibliothèques WebAssembly qui n’exfiltrent pas de données utiles
Par exemple, si canvas ne donnait accès qu’au buffer d’image sans routine de rendu appelant des bibliothèques spécifiques à la plateforme, sa valeur pour le fingerprinting serait bien plus faible
Dans les cas que j’ai vus jusqu’ici, cela servait par exemple à mettre en cache des images persistantes sur gmail, ou à maintenir l’état de connexion autrement qu’avec des cookies
J’étais un peu perdu sur ce point
Si l’UUID d’IndexedDB est partagé entre toutes les origines, ne pourrait-on pas identifier le navigateur à partir du contenu même de la base de données plutôt que de son ordre ?
Si une page crée les bases de données
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,ppuis interroge leur ordre, elle peut obtenir par exempleg,c,p,a,l,f,n,d,j,b,o,h,e,m,i,kselon le mappage global nom-UUIDLe cœur de la vulnérabilité est que, tant que le processus Firefox reste en vie, n’importe quel site web qui crée le même ensemble de bases, indépendamment de leur contenu, verra exactement le même ordre
Cela devient donc un identifiant stable à forte entropie persistant dans le temps, autrement dit un fingerprint
Il est partagé entre origines, et même après suppression des données du site, il suffit de recréer les bases sous les mêmes noms pour réobtenir l’empreinte via l’ordre
Sinon, IndexedDB serait un evercookie beaucoup trop facile
Chaque origine n’expose qu’un sous-ensemble des bases de données associées à cette origine
Je me demandais si Tor Browser autorise toujours JavaScript par défaut
Si j’ai bien compris, désactiver l’exécution de JavaScript empêcherait sans doute aussi cette vulnérabilité d’avoir un effet
Il n’y a pas beaucoup d’utilisateurs qui le désactivent, donc on se retrouve immédiatement dans un groupe bien plus petit, au sein duquel il est plus facile d’être unique
Bien sûr, sans JS, les possibilités de collecter des détails diminuent, mais il devient aussi plus facile de distinguer quelqu’un avec moins d’informations
Et, curieusement, Tor Browser ne spoofe pas du tout
navigator.platform, si bien que même si le User-Agent prétend être Windows, le site peut toujours voir que l’utilisateur est sous Linux