1 pontos por GN⁺ 14 일 전 | Ainda não há comentários. | Compartilhar no WhatsApp
  • Apenas a ordem de retorno de indexedDB.databases() já permite gerar um identificador estável que persiste durante a vida do processo em navegadores baseados em Firefox
  • Esse identificador é compartilhado além do escopo de origin, permitindo que sites sem relação entre si observem o mesmo valor dentro do mesmo runtime do navegador e o usem para rastreamento cross-origin
  • No Private Browsing do Firefox, o identificador continua existindo se o processo seguir vivo mesmo após fechar todas as janelas privadas, e permanece até depois de um New Identity no Tor Browser
  • A causa está na implementação do IndexedDB no Gecko, que mapeia nomes de bancos de dados privados para nomes de arquivo baseados em UUID e expõe o resultado sem ordenação
  • A Mozilla distribuiu a correção no Firefox 150 e no ESR 140.10.0, e projetar o sistema sem expor a ordem interna do armazenamento é essencial para proteger a privacidade

Visão geral da vulnerabilidade

  • Em todos os navegadores baseados em Firefox, é possível extrair um identificador que persiste durante a vida do processo pela ordem dos itens retornados por indexedDB.databases()
    • Se um site criar vários bancos de dados IndexedDB e depois verificar a ordem de retorno, ele pode gerar um identificador único e determinístico do processo do navegador em execução
    • Esse comportamento aparece no escopo do processo, não no escopo de origin, então até sites sem relação entre si podem observar o mesmo identificador dentro do mesmo runtime do navegador
  • No Private Browsing do Firefox, o identificador permanece se o processo do Firefox continuar em execução mesmo depois de fechar todas as janelas privadas
    • No Tor Browser, o identificador estável continua existindo até depois de um New Identity, que apaga cookies e histórico e usa um novo circuito Tor
    • Isso entra em conflito com a expectativa de que a atividade posterior do navegador não possa ser vinculada à atividade anterior, enfraquecendo a garantia de não vinculação na qual o usuário confia
  • Foi feita uma divulgação responsável à Mozilla e ao Tor Project
    • A Mozilla distribuiu a correção no Firefox 150 e no ESR 140.10.0
    • O patch está sendo acompanhado no Mozilla Bug 2024220, e a causa está na implementação do IndexedDB do Gecko, afetando também o Tor Browser e outros navegadores baseados em Firefox
  • O princípio da correção é simples
    • O navegador não deve expor externamente a ordem interna do armazenamento no escopo do processo
    • Se os resultados forem normalizados ou retornados em ordem classificada, é possível eliminar a entropia e bloquear o abuso desse identificador estável

Por que isso importa

  • O modo de navegação privada e os navegadores focados em privacidade existem para dificultar a identificação do usuário em contextos diferentes
    • Expectativa geral 1: na ausência de armazenamento compartilhado ou de mecanismos explícitos de identidade, sites sem relação entre si não deveriam conseguir saber se estão interagindo com a mesma instância do navegador
    • Expectativa geral 2: quando uma sessão privada termina, as informações associadas a ela também deveriam desaparecer
  • Esse comportamento quebra as duas expectativas
    • Um site pode derivar um identificador apenas a partir do comportamento interno de armazenamento do navegador, sem cookies, localStorage ou canais explícitos entre sites
    • A ordem dos nomes de bancos de dados retornada pela API fornece um sinal de identificação de alta capacidade
  • Há uma lição importante do ponto de vista de desenvolvimento
    • Vulnerabilidades de privacidade não surgem apenas do acesso direto a dados identificadores
    • Também pode haver vazamento de privacidade quando detalhes internos de implementação são expostos de forma determinística
  • Ponto central sob a ótica de segurança e produto
    • Mesmo uma API aparentemente inofensiva pode virar um vetor de rastreamento entre sites se vazar um estado estável em nível de processo

IndexedDB e indexedDB.databases()

  • IndexedDB é uma API de navegador para armazenamento estruturado de dados no lado do cliente
    • Aplicações web a utilizam para suporte offline, cache, estado de sessão e outros fins de armazenamento local
    • Cada origin pode criar um ou mais bancos de dados nomeados, com object stores e armazenamento de grandes volumes de dados
  • indexedDB.databases() retorna metadados dos bancos de dados visíveis para o origin atual
    • Desenvolvedores podem usar isso para verificar bancos existentes, depurar uso de armazenamento e gerenciar o estado da aplicação
  • Sob expectativas normais de proteção de privacidade, a própria ordem de retorno dessa API não deveria carregar informações identificadoras
    • É necessária uma representação neutra ou normalizada dos metadados dos bancos de dados
    • O problema real foi que, em navegadores baseados em Firefox, a ordem de retorno não era neutra de forma alguma

Como indexedDB.databases() virou um identificador estável

  • No Private Browsing do Firefox, indexedDB.databases() retorna metadados em uma ordem derivada da estrutura interna de armazenamento, e não da ordem de criação dos bancos de dados
    • A implementação relacionada fica em dom/indexedDB/ActorsParent.cpp
  • No Private Browsing, os nomes dos bancos de dados não são usados diretamente como identificadores em disco
    • Em vez disso, eles são mapeados para uma base de nome de arquivo baseada em UUID por meio da tabela hash global StorageDatabaseNameHashtable = nsTHashMap<nsString, nsString>
    • Esse mapeamento ocorre em GetDatabaseFilenameBase() dentro de OpenDatabaseOp::DoDatabaseWork()
  • Quando aIsPrivate é true, o nome do banco de dados fornecido pelo site é substituído por um UUID gerado e armazenado na StorageDatabaseNameHashtable global
    • A chave usa apenas a string do nome do banco de dados
    • Persiste durante a vida do QuotaClient do IndexedDB
    • É compartilhado entre todos os origins
    • Só é reinicializado quando o Firefox é totalmente reiniciado
  • Depois, ao chamar indexedDB.databases(), o Firefox coleta os nomes de arquivo dos bancos em GetDatabasesOp::DoDatabaseWork() por meio de QuotaClient::GetDatabaseFilenames(...)
    • Os nomes-base dos bancos são inseridos em um nsTHashSet
    • Nenhuma ordenação é feita antes da iteração
  • A ordem final dos resultados é determinada pelo percurso do layout interno dos buckets do conjunto hash
    • Como o mapeamento UUID permanece estável durante a vida do processo do Firefox, a ordem retornada também permanece como uma função determinística dos valores UUID gerados, do comportamento da função de hash, da capacidade da tabela hash e do histórico de inserção
    • Essa ordem persiste entre abas e janelas privadas, sendo redefinida apenas com um reinício completo do Firefox
    • Tanto o mapeamento UUID quanto a iteração do conjunto hash existem no escopo do processo, e não no escopo de origin

Como reproduzir

  • É possível demonstrar o comportamento com um PoC simples
    • Dois origins diferentes hospedam o mesmo script
    • Cada script cria bancos de dados com um conjunto fixo de nomes, chama indexedDB.databases(), extrai a ordem retornada e a imprime
  • Em builds afetadas do Firefox Private Browsing e do Tor Browser, os dois origins observam a mesma permutação durante a vida do mesmo processo do navegador
    • Ao reiniciar o navegador, a permutação muda
  • Exemplo conceitual de saída
    • Ordem de criação: a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p
    • Ordem de retorno: g,c,p,a,l,f,n,d,j,b,o,h,e,m,i,k
  • O ponto principal não é a ordem exata em si
    • Ela difere da ordem de criação original
    • A mesma ordem aparece em origins sem relação entre si
    • Persiste após recarregar a página, abrir uma nova janela privada e até depois de fechar todas as janelas privadas
    • Só uma reinicialização completa do navegador gera uma nova ordem
    • Isso permite verificar diretamente uma propriedade indesejada do ponto de vista da privacidade

Impacto na privacidade

  • Essa vulnerabilidade permite tanto rastreamento cross-origin quanto same-origin dentro de um único runtime do navegador
  • Impacto cross-origin

    • Sites sem relação entre si podem derivar independentemente o mesmo identificador e inferir que estão interagindo com o mesmo processo em execução do Firefox ou do Tor Browser
    • Torna possível vincular atividades entre domínios mesmo sem cookies ou outro armazenamento compartilhado
  • Impacto same-origin

    • No Private Browsing do Firefox, o identificador permanece se o processo do Firefox continuar em execução mesmo depois de todas as janelas privadas serem fechadas
    • Um site pode reconhecer novamente visitas posteriores que aparentam ser uma nova sessão privada
    • No Tor Browser, o identificador estável praticamente neutraliza o isolamento de New Identity dentro do processo do navegador em execução
    • Isso permite vincular sessões que deveriam estar totalmente separadas
  • Por que isso é especialmente grave no Tor Browser

    • O Tor Browser foi projetado para reduzir a possibilidade de ligação entre sites e minimizar a identificação em nível de instância do navegador
    • Um identificador estável que persiste durante a vida do processo entra em choque direto com esse objetivo de design
    • Mesmo sobrevivendo apenas até um reinício completo do processo, isso já basta para enfraquecer a não vinculação durante uso ativo

Entropia e capacidade de fingerprinting

  • Esse sinal não é apenas estável, como também tem alta capacidade
    • Se um site controla N nomes de bancos de dados, o número de permutações observáveis é N!
    • A entropia teórica é log2(N!)
  • Com 16 nomes controláveis, o espaço teórico é de cerca de 44 bits
    • Um nível suficiente para distinguir instâncias simultâneas de navegador em ambientes reais
  • Por causa do comportamento da tabela hash interna, o número de permutações realmente atingível pode ser um pouco menor
    • Mas isso não muda o ponto central do ponto de vista de segurança
    • A ordem exposta ainda fornece entropia suficiente para funcionar como um identificador forte

Como corrigir

  • A correção correta é interromper a exposição de entropia derivada do layout interno do armazenamento
    • A mitigação mais limpa é retornar os resultados em uma ordem canônica, como ordenação lexicográfica
    • Isso preserva a utilidade da API para desenvolvedores enquanto remove o sinal de fingerprinting
  • Randomizar a saída a cada chamada também poderia ocultar a ordem estável
    • Ainda assim, ordenar é uma opção mais simples, previsível e fácil para desenvolvedores entenderem
  • Condições ideais da correção sob a ótica de engenharia de segurança
    • Baixa complexidade conceitual
    • Risco mínimo de compatibilidade
    • Eliminação direta do vazamento de privacidade

Divulgação responsável

  • Foi feita uma divulgação responsável à Mozilla e ao Tor Project
    • A Mozilla distribuiu a correção no Firefox 150 e no ESR 140.10.0
    • O patch está sendo acompanhado no Mozilla Bug 2024220
  • A origem do comportamento está na implementação do IndexedDB do Gecko
    • Navegadores derivados do Gecko, incluindo o Tor Browser, também entram na área de impacto se não tiverem uma mitigação própria

Design centrado em privacidade

  • Até pequenos detalhes de implementação podem levar a problemas relevantes de privacidade
    • Sites sem relação entre si podem vincular atividades além do origin durante o mesmo runtime do navegador
    • O identificador sobrevive mais tempo do que o usuário espera, enfraquecendo os limites de sessões privadas
  • O lado positivo é que a correção é simples e eficaz
    • Normalizar a saída antes de retorná-la remove essa fonte de entropia
    • Isso permite restaurar os limites de privacidade esperados
  • É um tipo de vulnerabilidade fácil de ignorar, mas com grande impacto e que merece atenção especial ao criar funcionalidades sensíveis à privacidade

Ainda não há comentários.

Ainda não há comentários.