1 pontos por GN⁺ 2024-03-11 | 1 comentários | Compartilhar no WhatsApp
  • O Safari 17 adiciona ruído aleatório a cada amostra da Audio API no modo privado para embaralhar a impressão digital de áudio, mas a FingerprintJS respondeu com um novo algoritmo de fingerprint para reduzir esse efeito
  • O método anterior usava a soma de 500 amostras de áudio como identificador, então a faixa de ruído do Safari ficou maior que as diferenças entre navegadores, fazendo-o perder estabilidade
  • O novo método cria em grande quantidade cópias ruidosas da mesma amostra de áudio e reduz a oscilação dos valores com (min+max)/2 e arredondamento por algarismos significativos
  • Ao conectar OscillatorNode square, DynamicsCompressorNode e BiquadFilterNode, eles ampliaram as diferenças entre navegadores e elevaram a menor diferença da amostra 3396 entre os navegadores selecionados para 0.0014%
  • O novo algoritmo substituiu a impressão digital de áudio anterior a partir do FingerprintJS 4.2.0; o tempo de cálculo aumenta de 1,5 a 2 vezes, mas ainda termina rapidamente mesmo em dispositivos de baixo desempenho

Como o Safari 17 embaralha a impressão digital de áudio

  • A impressão digital de áudio renderiza um sinal de áudio com a Audio API e o OfflineAudioContext, depois soma as amostras para gerar um único número identificador
  • Esse identificador tem estabilidade, pois não muda mesmo após apagar cookies ou alternar para o modo anônimo, mas sua unicidade não é alta porque muitos usuários podem compartilhar o mesmo valor
  • A proteção avançada contra fingerprint do Safari 17 fica ativada por padrão no modo privado e desativada no modo normal, valendo tanto para desktop quanto para mobile
  • A proteção também afeta a Screen API e a Canvas API, mas aqui o foco é apenas a Audio API
  • Quando a proteção está ativada, o Safari multiplica cada amostra de áudio por um ruído aleatório individual
    • A amostra com ruído fica entre sample*(1-magnitude) e sample*(1+magnitude)
    • A distribuição é uniforme
    • Como o desenvolvimento do Safari continua, os detalhes de implementação podem mudar com o tempo

Pontos da Audio API onde o ruído é aplicado

  • O Safari aplica ruído em várias interfaces pelas quais é possível ler o sinal de áudio
  • Como o ruído muda a cada aplicação, a impressão digital de áudio no modo privado do Safari 17 muda a cada cálculo
  • No Safari 17 de um M1 MacBook Air, a fingerprint varia entre 124.03516 e 124.04545, uma diferença de cerca de 0.008%
  • Entre as diferenças da impressão digital de áudio anterior por navegador, o menor valor era 0.0000023%, muito menor que a faixa de ruído do Safari
  • Para eliminar o ruído seria preciso arredondar para algo como uma casa decimal, mas com menos de 6 dígitos restantes fica difícil distinguir alguns navegadores, reduzindo a unicidade

As 3 etapas do novo algoritmo

  • O novo algoritmo de impressão digital de áudio da FingerprintJS passa por três etapas para reduzir o ruído adicionado pelo Safari
    • Reduz a variância do ruído
    • Aumenta a distância entre os números identificadores dos navegadores
    • Remove o ruído restante com arredondamento
  • Como a fingerprint de áudio anterior era a soma de 500 amostras de áudio, quando se adiciona ruído de distribuição uniforme a cada amostra, o ruído total da fingerprint se aproxima de uma distribuição normal
  • A média de uma distribuição normal precisa ser estimada pela média de muitas amostras, mas a média de uma distribuição uniforme pode ser estimada com precisão a partir de menos amostras usando (min+max)/2
  • No código experimental, sob as mesmas condições de precisão, a distribuição normal exigiu 524,288 amostras, enquanto a uniforme precisou de apenas 4,096
  • Em vez da fingerprint por soma, o novo método passou a coletar apenas uma única amostra de áudio, para lidar com ruído de distribuição uniforme
  • Por causa dessa mudança, a nova fingerprint não é compatível com a anterior, e é necessária uma abordagem separada para migrar sem perder os identificadores dos visitantes

Criando cópias ruidosas da mesma amostra de áudio

  • Chamar getChannelData várias vezes em uma instância de AudioBuffer não funciona
    • O ruído é aplicado uma vez por instância de AudioBuffer
    • getChannelData da mesma instância retorna o mesmo sinal
  • É possível criar muitas instâncias de AudioBuffer repetindo todo o processo de geração do sinal de áudio, mas isso é lento demais para calcular fingerprint
    • 6,000 amostras de ruído levaram no mínimo 7 segundos em um M1 MacBook
    • Com 60,000, o Safari não conseguiu concluir a tarefa
  • Um método melhor é criar uma instância de AudioBuffer que repita o mesmo sinal de áudio
    • O primeiro sinal de áudio é renderizado, mas getChannelData não é chamado
    • Em seguida, cria-se um segundo OfflineAudioContext mais longo, usando o sinal original como AudioBufferSourceNode
    • loop, loopStart e loopEnd repetem parte do sinal original
    • Como o Safari adiciona ruído após a repetição, obtêm-se cópias da mesma amostra de áudio com ruídos diferentes
  • Esse método permite criar a quantidade necessária de cópias com ruído com apenas 2 renderizações de áudio
  • O ruído não desaparece completamente, mas a variância fica menor que na amostra de áudio original
    • 8,192 cópias: faixa de 0.000387% em 100 execuções, 2.6ms em um M1 MacBook
    • 65,536 cópias: 0.0000123%, 4.1ms
    • 262,144 cópias: 0%, 7.5ms

Aumentando a diferença entre amostras de áudio dos navegadores

  • Reduzir o número de cópias melhora o desempenho, mas aumenta a variância do resultado; por isso, o sinal base foi alterado para ampliar as diferenças entre navegadores
  • Após testar vários nós de áudio embutidos, a cadeia de geração de sinal que mais aumentou as diferenças entre amostras de navegadores foi a seguinte
  • A amostra de número 3396 do sinal de áudio foi a que apresentou a maior diferença entre navegadores, valor encontrado comparando todas as amostras de vários navegadores
  • Na amostra de navegadores selecionada, a menor diferença dessa nova amostra foi 0.0014%
    • Maior que a menor diferença da fingerprint anterior, 0.0000023%
    • Isso permitiu aplicar remoção de ruído mais agressiva e arredondamento mais grosseiro

Estabilizando a fingerprint com arredondamento

  • Mesmo com a faixa de ruído de uma única amostra reduzida, o valor ainda oscila, então é preciso arredondar para usá-lo como fingerprint final
  • Como o ruído é aplicado em relação ao valor da amostra de áudio, e não em valor absoluto, o arredondamento é feito com base em algarismos significativos, não em casas decimais
  • Para distinguir os navegadores selecionados, 5 algarismos significativos eram suficientes, mas como não é possível verificar todos os navegadores e mudanças futuras, foram usados mais dígitos
  • No modo privado do Safari 17, o número de cópias necessário para estabilizar cada nível de precisão de arredondamento foi o seguinte
    • 6 algarismos significativos: 15,000 cópias, 3ms no Safari 17 em um M1 MacBook aquecido
    • 7 algarismos significativos, mas arredondando o último dígito para múltiplos de 5: 30,000 cópias, 4ms
    • 7 algarismos significativos, mas arredondando o último dígito para o número par mais próximo: 70,000 cópias, 6ms
    • 7 ou mais algarismos significativos: 400,000 cópias, 12ms
  • A escolha final foi 7 algarismos significativos, com o último dígito sendo 0 ou 5, e o número de cópias foi aumentado para 40,000 para melhorar a estabilidade
  • Esse número arredondado passa a ser a nova fingerprint de áudio, que não muda mesmo com a proteção avançada contra fingerprint do Safari 17 ativada
  • A nova fingerprint foi avaliada como tendo a mesma unicidade da impressão digital de áudio anterior

Desempenho e restrições de execução

  • Em um navegador aquecido numa página vazia, o novo algoritmo é, em geral, mais lento que o anterior
    • MacBook Air 2020 Safari 17.3: método anterior 2ms, novo método 4ms
    • MacBook Air 2020 Chrome 120: método anterior 5ms, novo método 8ms
    • iPhone 13 mini Safari 17.3: método anterior 8ms, novo método 12ms
    • Galaxy J7 Prime Chrome 120: método anterior 33ms, novo método 45ms
    • BrowserStack Windows 11 Firefox 121: método anterior 10ms, novo método 18ms
  • O desempenho do novo algoritmo piora em 1,5 a 2 vezes em relação ao anterior, mas o tempo de cálculo continua curto mesmo em dispositivos modestos
  • Como o navegador delega parte do trabalho para a thread OfflineAudioRender, a página permanece responsiva durante a maior parte do cálculo da fingerprint de áudio
  • A Web Audio API não pode ser usada em web workers, então não é possível calcular a fingerprint de áudio em um worker
  • Para melhorar o desempenho, é possível verificar pela string do user agent se é Safari 17 ou superior e usar o novo algoritmo apenas no Safari 17+, mantendo o antigo nos demais navegadores

Diferenças entre Tor e Brave

  • O Tor desativa completamente a Web Audio API, então a impressão digital de áudio é impossível
  • O Brave adiciona ruído ao sinal de áudio como o Safari 17, mas de forma diferente
  • O Safari multiplica cada amostra de áudio por um valor aleatório separado
  • O Brave gera uma única multiplicação aleatória chamada fudge factor e aplica o mesmo valor a todas as amostras de áudio
    • Esse valor é mantido dentro da página
    • Só muda em uma nova sessão normal ou anônima
  • No Brave, por mais cópias de amostras de áudio que se criem, todas recebem o mesmo ruído, então o método matemático de remoção de ruído pensado para o Safari não funciona
  • Ainda assim, o método anterior de remoção de ruído do Brave continua funcionando, e o novo método de geração de sinal que amplia a diferença entre fingerprints de navegadores pode aumentar a margem de erro tolerável

Aplicação no FingerprintJS

  • O novo algoritmo de impressão digital de áudio substituiu o método anterior no FingerprintJS e foi publicado pela primeira vez na 4.2.0
  • O código completo da implementação está no repositório GitHub da FingerprintJS
  • A fingerprint de áudio é um dos vários sinais usados pela biblioteca open source para criar a impressão digital do navegador
  • A FingerprintJS não inclui automaticamente todos os sinais disponíveis no navegador; ela analisa separadamente a estabilidade e a unicidade de cada sinal para avaliar seu impacto na precisão da fingerprint
  • A fingerprint de áudio é considerada um sinal que contribui pouco para a unicidade, mas cuja alta estabilidade melhora ligeiramente a precisão geral da fingerprint

1 comentários

 
GN⁺ 2024-03-11
Comentários no Hacker News
  • Outra técnica interessante para identificar usuários online é a impressão digital da GPU, apresentada em 2022 com o codinome "DrawnApart"
    Ela conta o número e a velocidade das unidades de execução da GPU via WebGL e mede coisas como o tempo de conclusão da renderização de vértices e o processamento de funções de stall

    1. https://www.bleepingcomputer.com/news/security/researchers-u...
    • Os navegadores deveriam usar renderizadores por software por padrão e, ao abrir o caminho de renderização por GPU de hardware, deveriam pedir permissão ao usuário para o site, como fazem com microfone ou câmera
  • Hoje em dia, especialmente considerando o interesse em ataques por canal lateral, a abordagem de adicionar ruído uniforme aos valores pelos quais os dados vazam quase certamente não funciona
    Isso porque, coletando mais amostras, é possível remover o ruído. Não sei por que o Safari adicionou isso. Pode tornar a coleta de impressões digitais mais trabalhosa, mas, como neste artigo, no fim parece que em geral dá para contornar de alguma forma

    • Acho que muitos dos recursos recentes de privacidade da Apple são mais marketing
      Parece uma espécie de teatro da privacidade, em que o mais importante passou a ser ter uma história plausível para contar ao público, e não se a solução é tecnicamente eficaz
  • Alguém pode explicar por que os resultados são diferentes, para começo de conversa? Por exemplo, queria entender por que a impressão digital de áudio é possível

    • O ponto principal parece ser que a Web Audio API tem algoritmos que fazem muitas operações matemáticas, que a implementação varia um pouco de navegador para navegador, e que os resultados exatos também dependem do sistema operacional e da CPU
      Ao criar um pequeno sinal com a Web Audio API, todos os navegadores produzem resultados quase iguais, mas é possível diferenciá-los usando diferenças minúsculas
    • Acho que é parecido com técnicas semelhantes usadas em WebGL, em que muita entropia vem do driver da placa de vídeo do PC e do próprio hardware
      É uma pena que os desenvolvedores de navegadores tenham que adicionar ruído ao processamento de buffers de áudio para tentar impedir isso
    • Também foi a primeira coisa em que pensei, e isto trata do assunto com mais detalhes: https://fingerprint.com/blog/audio-fingerprinting/#why-the-a...
      Em resumo, mesmo dentro da mesma base de código, caminhos de código diferentes, como variantes SIMD, podem produzir resultados de ponto flutuante sutilmente diferentes. Isso parece estar relacionado ao fato de que operações de ponto flutuante são mais sensíveis do que se imagina à ordem das operações, entre outras coisas
    • É bem provável que seja por causa de detalhes de implementação e otimizações do compilador. Por exemplo, a adição de ponto flutuante não é comutativa
      Mesmo implementando corretamente o mesmo algoritmo e as mesmas fórmulas, os resultados podem variar um pouco
  • Corrijam-me se eu estiver errado. O motivo pelo qual o desvio da impressão digital funciona aqui parece se resumir à decisão da especificação da Web Audio API de deixar em aberto desta forma o tratamento de anti-aliasing do OscillatorNode
    "Há várias abordagens práticas que uma implementação pode adotar para evitar esse aliasing. Independentemente da abordagem, o sinal de áudio digital ideal em tempo discreto é matematicamente bem definido. As concessões da implementação estão no custo de implementação em termos de uso de CPU e em quão fielmente ela chega a esse ideal. Embora se espere que as implementações tomem algum cuidado para atingir esse ideal, em hardware de baixo desempenho é razoável considerar abordagens de qualidade mais baixa e custo mais baixo."
    Na minha visão, isso significa que a saída do OscillatorNode explorada aqui quase certamente não é determinística entre navegadores e até mesmo entre hardwares diferentes no mesmo navegador. A não determinismo se baseia no método de anti-aliasing escolhido pelo navegador ou nos vários caminhos escolhidos dentro do mesmo navegador conforme o hardware. Isso também inclui mudanças ou correções no mesmo algoritmo de anti-aliasing
    Não sei bem por que o anti-aliasing foi deixado a cargo do navegador. Aplicativos ou bibliotecas de áudio de alta qualidade vão querer controlar totalmente a forma como evitam aliasing nos sinais que geram, e não usarão o oscilador padrão. Por outro lado, se um web app aceita um algoritmo arbitrário de anti-aliasing e as diferenças por navegador decorrentes disso, provavelmente não vai se importar muito se o algoritmo são instruções SIMD hardcoded ou um framework auxiliar JavaScript de Web Audio de 20 MB
    1: https://webaudio.github.io/web-audio-api/#OscillatorNode
    Fico imaginando se aqui não seria possível aplicar a mesma solução que Hixie usou ao padronizar o parser de HTML5: um especialista da área especifica um algoritmo de anti-aliasing exato e determinístico que funcione suficientemente bem, e depois todos os navegadores passam a usá-lo. A perda de desempenho mensurável provavelmente só apareceria em algo como tutoriais da Web Audio API que geram sinais com o oscilador padrão com anti-aliasing

    • Anti-aliasing de alta qualidade é caro
      Por isso, a ideia é permitir que a implementação decida quanto gastar conforme os recursos de computação disponíveis, bateria etc.
  • Foi uma tolice colocar uma API de áudio em grafo de nós no navegador. Deveria ter havido apenas AudioWorklet

  • Repulsivo

    • Penso exatamente o mesmo. Interessante, mas repulsivo.
      Para começo de conversa, não entendo por que a API de áudio pode ser usada sem permissão do site. Parece algo fácil de corrigir com uma caixa de diálogo simples, tipo "Este site quer usar seu dispositivo de som".
    • Isso faz a gente se perguntar se dá para continuar usando a pilha de rede atual pelos próximos 100 anos.
      A Internet em sua forma atual arruinou muito do sonho da computação pessoal. Empresas e Estados são poderosos demais de forma assimétrica em relação aos indivíduos. A minha tecnologia deveria poder enviar dados para um servidor sem aprovação explícita?
    • Sim. Não dá para acreditar que essas pessoas se orgulhem disso.
      Por outro lado, quando limpei o cache do navegador e liguei a VPN, ele me identificou erroneamente como um novo visitante. Ainda assim, o modelo de negócios é desprezível.
    • Achei que havia certa ironia em ser fingerprint.com. É parecido com aparecer um site que populariza uma brecha para evitar impostos, fazendo o mundo ficar enojado e fechar essa brecha.
      Mesmo sendo uma interpretação otimista, há muito valor em publicar pesquisas assim e trazê-las à tona. Em vez de me preocupar que todo mundo vá roubar mais porque saiu um texto dizendo que uma mochila verde de uma certa marca ajuda em furtos, eu tenderia a apostar mais que as lojas passarão a perceber melhor esse método.
  • Em vez de somar valores aleatórios a cada amostra, parece que o Safari também poderia adicionar ruído determinístico com base em uma chave que muda a cada hora.
    Se for criado como uma função das amostras de áudio e da chave, o ruído seria o mesmo dentro da mesma sessão, mas se tornaria inútil para rastreamento uma hora depois.

    • Se você tirar a média de 10 dessas amostras, no fim chega perto do valor real do dispositivo. Quanto mais amostras, mais perto vai chegar.
      Para corrigir isso, é preciso eliminar o vazamento de informação em si; apenas escondê-lo sob uma camada de desvio aleatório não basta.
    • Não ajudaria se o ruído adicionado fosse determinístico com base na origem (origin)? Assim, mesmo com amostragem excessiva, não daria para removê-lo tirando a média.
      Por exemplo, algo como RNG_SEED = HMAC_SHA256(PERSISTENT_SECRET,Location.origin).
  • Agora estou realmente pronto para virar "aquela pessoa" que navega na Web com o JavaScript desligado.

    • O problema é que só de virar "aquela pessoa" você provavelmente já entrega mais de 10 bits para identificação.
      Se eles conseguirem raspar só mais alguns bits de outros lugares, você pode ser identificado de forma única. Mesmo assim, para mim, esse pessoal pode ser colocado na Golgafrinchan Ark B junto com o resto da indústria de adtech.
    • Boa sorte. É surpreendente como há pouco HTML antigo e decente na Web hoje em dia.
      Um site que visitei recentemente até usava marcação, mas em vez de compilá-la para HTML e servi-la estaticamente, renderizava tudo no lado do cliente com JavaScript. WTF.
    • Vamos nessa, dá para fazer na prática. Existe uma ótima extensão para Firefox chamada uMatrix, que permite desativar JavaScript facilmente não só por site, mas também por subdomínio, e também torna fácil reativar em sites que quebram sem JavaScript.
    • Boa sorte. Desisti dessa briga recentemente, porque em praticamente todos os sites que eu visitava precisava religar o JavaScript para ver o conteúdo.
      Não são só verificações de DDoS como as da Cloudflare; agora até coisas que deveriam estar dentro do HTML da página são carregadas via JavaScript.
    • É exatamente por esse motivo que o Tor Browser deveria deixar o JavaScript desligado.
      Quanto mais hostil a Internet fica, mais essa escolha vai na direção certa.
  • Não entendo bem como esse método consegue criar mais do que alguns milhares de combinações únicas.
    Tipo de navegador × versão do navegador × versão do sistema operacional × versão do acelerador × … o que mais? Não parece haver variação suficiente para ser remotamente único.

    • Combinatória é uma senhora cruel.
  • Essa técnica faz fingerprinting com base em diferenças de hardware, drivers e sistema operacional no processamento de áudio, ou olha apenas para o software do navegador?
    Imagino que tenha existido, ou ainda exista, uma técnica parecida que expõe diferenças do dispositivo gráfico subjacente.

    • É algo parecido. Algoritmos de áudio muitas vezes chamam funções do sistema operacional e aproveitam otimizações de CPU.
      Um dos exemplos dados no texto é a Transformada Rápida de Fourier (FFT). Todos os sistemas operacionais têm uma versão dessa função, mas ela tende a ser otimizada ao longo do tempo, e frequentemente se comporta de forma diferente em CPUs diferentes dependendo das instruções SIMD disponíveis.