Descubrimos un identificador estable de Firefox que vincula todas las identidades privadas de Tor de un usuario
(fingerprint.com)- Solo con el orden de retorno de
indexedDB.databases()es posible generar un identificador estable que se mantiene durante la vida del proceso en navegadores basados en Firefox - Este identificador se comparte más allá del alcance del origin, por lo que incluso sitios no relacionados pueden observar el mismo valor dentro del mismo tiempo de ejecución del navegador y usarlo para rastreo cross-origin
- En Private Browsing de Firefox, el identificador se mantiene aunque se cierren todas las ventanas privadas si el proceso sigue vivo, y también persiste después de New Identity en Tor Browser
- La causa está en que la implementación de IndexedDB de Gecko asigna los nombres de bases de datos privadas a nombres de archivo basados en UUID y expone ese resultado sin ordenarlo
- Mozilla publicó la corrección en Firefox 150 y ESR 140.10.0; diseñar el sistema para no exponer hacia afuera el orden del almacenamiento interno es importante para proteger la privacidad
Resumen de la vulnerabilidad
- En todos los navegadores basados en Firefox, es posible extraer un identificador que perdura durante la vida del proceso a partir del orden de los elementos devueltos por
indexedDB.databases()- Si un sitio web crea varias bases de datos de IndexedDB y luego revisa el orden de retorno, puede generar un identificador único y determinista del proceso del navegador en ejecución
- Este comportamiento no aparece a nivel de origin sino a nivel de proceso, por lo que sitios no relacionados pueden observar el mismo identificador dentro del mismo tiempo de ejecución del navegador
- En Private Browsing de Firefox, el identificador se conserva aunque se cierren todas las ventanas privadas, siempre que el proceso de Firefox siga en ejecución
- En Tor Browser, el identificador estable permanece incluso después de New Identity, que borra cookies e historial y usa un nuevo circuito de Tor
- Esto entra en conflicto con la expectativa de que la actividad posterior no debería poder vincularse con la anterior, debilitando la garantía de desvinculación en la que confía el usuario
- Se realizó una divulgación responsable a Mozilla y al Tor Project
- Mozilla distribuyó la corrección en Firefox 150 y ESR 140.10.0
- El parche se sigue en Mozilla Bug 2024220, y la causa está en la implementación de IndexedDB de Gecko, por lo que también afecta a Tor Browser y a otros navegadores basados en Firefox
- El principio de la corrección es simple
- El navegador no debería exponer hacia afuera el orden del almacenamiento interno con alcance de proceso
- Si los resultados se normalizan o se devuelven ordenados, se puede eliminar la entropía y bloquear el abuso de este identificador estable
Por qué importa
- El modo de navegación privada y los navegadores centrados en la privacidad buscan dificultar la identificación del usuario entre distintos contextos
- Expectativa general 1: salvo que exista almacenamiento compartido o un mecanismo de identidad explícito, sitios no relacionados no deberían poder saber si están interactuando con la misma instancia del navegador
- Expectativa general 2: cuando termina una sesión privada, también debería desaparecer la información asociada con esa sesión
- Este comportamiento rompe ambas expectativas
- Un sitio puede derivar un identificador a partir del comportamiento interno del almacenamiento del navegador sin cookies,
localStorageni canales explícitos entre sitios - El orden de los nombres de bases de datos devuelto por la API puede ofrecer una señal de identificación de alta capacidad
- Un sitio puede derivar un identificador a partir del comportamiento interno del almacenamiento del navegador sin cookies,
- Hay una lección importante desde la perspectiva de desarrollo
- Las vulnerabilidades de privacidad no surgen solo por el acceso directo a datos identificatorios
- También puede haber filtraciones cuando detalles internos de implementación quedan expuestos de forma determinista
- Punto clave desde seguridad y producto
- Incluso una API aparentemente inocua puede convertirse en un vector de rastreo entre sitios si filtra un estado estable a nivel de proceso
IndexedDB y indexedDB.databases()
- IndexedDB es una API del navegador para almacenamiento estructurado de datos del lado del cliente
- Las aplicaciones web la usan para soporte offline, caché, estado de sesión y otros fines de almacenamiento local
- Cada origin puede crear una o más bases de datos con nombre y almacenar
object storey grandes volúmenes de datos
indexedDB.databases()devuelve metadatos de las bases de datos visibles para el origin actual- Los desarrolladores pueden usarla para revisar bases de datos existentes, depurar uso de almacenamiento y administrar el estado de la aplicación
- Bajo una expectativa normal de privacidad, el orden de retorno de esta API no debería contener información identificatoria
- Se necesita una representación neutral o normalizada de los metadatos de las bases de datos
- El problema real fue que, en los navegadores basados en Firefox, ese orden de retorno no era neutral en absoluto
Cómo indexedDB.databases() se convirtió en un identificador estable
- En Firefox Private Browsing,
indexedDB.databases()devuelve los metadatos no en orden de creación de la base de datos, sino en un orden derivado de la estructura de almacenamiento interna- La implementación relevante está en
dom/indexedDB/ActorsParent.cpp
- La implementación relevante está en
- En Private Browsing, los nombres de las bases de datos no se usan directamente como identificadores en disco
- En su lugar, se asignan a una base de nombre de archivo basada en UUID mediante la tabla hash global
StorageDatabaseNameHashtable = nsTHashMap<nsString, nsString> - Esa asignación se realiza en
GetDatabaseFilenameBase()dentro deOpenDatabaseOp::DoDatabaseWork()
- En su lugar, se asignan a una base de nombre de archivo basada en UUID mediante la tabla hash global
- Cuando
aIsPrivatees true, el nombre de la base de datos proporcionado por el sitio se reemplaza por un UUID generado y se guarda enStorageDatabaseNameHashtable- La clave usa únicamente la cadena del nombre de la base de datos
- Persiste durante la vida del QuotaClient de IndexedDB
- Se comparte entre todos los origins
- Solo se reinicia al cerrar por completo Firefox
- Más tarde, cuando se llama a
indexedDB.databases(), Firefox recopila los nombres de archivo de las bases de datos medianteQuotaClient::GetDatabaseFilenames(...)enGetDatabasesOp::DoDatabaseWork()- Los nombres base de las bases de datos se insertan en un
nsTHashSet - No se realiza ninguna ordenación antes de iterar
- Los nombres base de las bases de datos se insertan en un
- El orden final de resultados queda determinado por el recorrido de la distribución interna de buckets del conjunto hash
- Como la asignación UUID se mantiene estable durante la vida del proceso de Firefox, el orden de retorno también permanece como una función determinista de los valores UUID generados, del comportamiento de la función hash, de la capacidad de la tabla hash y del historial de inserciones
- Ese orden se mantiene entre pestañas y ventanas privadas, y solo se reinicia con un reinicio completo de Firefox
- Tanto la asignación UUID como la iteración del conjunto hash tienen alcance de proceso, no de origin
Cómo reproducirlo
- Se puede demostrar el comportamiento con un PoC simple
- Dos origins distintos alojan el mismo script
- Cada script crea bases de datos con un conjunto fijo de nombres, llama a
indexedDB.databases(), extrae el orden devuelto y lo muestra
- En versiones afectadas de Firefox Private Browsing y Tor Browser, ambos origins observan la misma permutación durante la vida del mismo proceso del navegador
- Al reiniciar el navegador, la permutación cambia
- Se muestra un ejemplo conceptual de salida
- Orden de creación:
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p - Orden de retorno:
g,c,p,a,l,f,n,d,j,b,o,h,e,m,i,k
- Orden de creación:
- Lo importante no es el orden exacto en sí
- Es distinto del orden original de creación
- El mismo orden aparece en origins no relacionados
- Se mantiene tras recargar, abrir una nueva ventana privada o incluso cerrar todas las ventanas privadas
- Solo se genera un nuevo orden al reiniciar por completo el navegador
- Esto permite verificar directamente una propiedad no deseada desde el punto de vista de la privacidad
Impacto en la privacidad
- Esta vulnerabilidad permite tanto rastreo cross-origin como same-origin dentro de un mismo tiempo de ejecución del navegador
-
Impacto cross-origin
- Sitios web no relacionados pueden derivar de forma independiente el mismo identificador e inferir que están interactuando con el mismo proceso en ejecución de Firefox o Tor Browser
- Eso permite vincular actividad entre dominios incluso sin cookies ni otro almacenamiento compartido
-
Impacto same-origin
- En Firefox Private Browsing, el identificador persiste aunque se cierren todas las ventanas privadas, siempre que el proceso de Firefox siga en ejecución
- Un sitio puede volver a reconocer visitas posteriores que aparentan ser una nueva sesión privada
- En Tor Browser, el identificador estable prácticamente anula el aislamiento de New Identity dentro del proceso del navegador en ejecución
- Esto permite vincular sesiones que deberían estar completamente separadas
-
Por qué es especialmente grave en Tor Browser
- Tor Browser está diseñado para reducir la posibilidad de vinculación entre sitios y minimizar la identificación a nivel de instancia del navegador
- Un identificador estable que dura toda la vida del proceso choca directamente con ese objetivo de diseño
- Aunque solo sobreviva hasta un reinicio completo del proceso, eso basta para debilitar la desvinculación durante el uso activo
Entropía y capacidad de fingerprinting
- Esta señal no solo es estable, también tiene alta capacidad
- Si un sitio controla
Nnombres de bases de datos, la cantidad de permutaciones observables esN! - La entropía teórica es
log2(N!)
- Si un sitio controla
- Con 16 nombres controlables, el espacio teórico es de aproximadamente 44 bits
- Eso alcanza para distinguir instancias concurrentes del navegador en entornos reales
- Debido al comportamiento de la tabla hash interna, la cantidad real de permutaciones alcanzables podría ser algo menor
- Sin embargo, eso no cambia el punto central desde el punto de vista de seguridad
- El orden expuesto sigue aportando suficiente entropía para funcionar como un identificador fuerte
Cómo se corrigió
- La corrección adecuada consiste en dejar de exponer la entropía derivada de la distribución del almacenamiento interno
- La mitigación más limpia es devolver los resultados en un orden canónico, como orden lexicográfico
- Así se conserva la utilidad de la API para los desarrolladores y se elimina la señal de fingerprinting
- Aleatorizar la salida en cada llamada también podría ocultar el orden estable
- Pero ordenar es una opción más simple, predecible y fácil de entender para los desarrolladores
- Se describen las condiciones ideales de la corrección desde la ingeniería de seguridad
- Baja complejidad conceptual
- Riesgo mínimo de compatibilidad
- Eliminación directa de la filtración de privacidad
Divulgación responsable
- Se realizó una divulgación responsable a Mozilla y al Tor Project
- Mozilla distribuyó la corrección en Firefox 150 y ESR 140.10.0
- El parche se sigue en Mozilla Bug 2024220
- El origen del comportamiento está en la implementación de IndexedDB de Gecko
- Los navegadores derivados de Gecko, incluido Tor Browser, también quedan dentro del alcance si no aplican mitigaciones propias
Diseño centrado en la privacidad
- Incluso pequeños detalles de implementación pueden convertirse en problemas de privacidad significativos
- Sitios no relacionados pueden vincular actividad más allá del origin durante el mismo tiempo de ejecución del navegador
- El identificador sobrevive más de lo que espera el usuario y debilita los límites de las sesiones privadas
- Lo positivo es que la corrección es simple y efectiva
- Normalizar la salida antes de devolverla elimina esta fuente de entropía
- Eso permite restaurar los límites de privacidad esperados
- Es un tipo de vulnerabilidad fácil de pasar por alto pero con gran impacto, y vale la pena tenerla muy presente al crear funciones sensibles a la privacidad
Aún no hay comentarios.