Guia de defesa contra impressão digital do navegador: do Canvas Fingerprinting a estratégias antirrastreamento focadas em privacidade

前端工程

Impressão digital do navegador: rastreamento sem cookies

Mesmo com cookies desativados e modo anônimo ativado, os sites podem identificá-lo de forma exclusiva por meio da impressão digital do navegador — com uma taxa de precisão de até 99,1%.

Tipo de impressão digital Estabilidade Singularidade Dificuldade de defesa
User-Agent Baixa (muda com atualizações) Média Baixa
Canvas Alta Alta Média
WebGL Alta Alta Média
AudioContext Alta Média Média
Enumeração de fontes Alta Alta Alta
Resolução de tela Alta Média Baixa
Fuso horário/Idioma Alta Baixa Baixa

1. Impressão digital Canvas

Como funciona

Diferentes GPU, drivers e algoritmos de anti-aliasing em diferentes dispositivos produzem diferenças sutis na mesma saída de renderização Canvas:

function getCanvasFingerprint() {
  const canvas = document.createElement('canvas');
  canvas.width = 200;
  canvas.height = 50;
  const ctx = canvas.getContext('2d');

  // Renderizar texto e formas
  ctx.textBaseline = 'top';
  ctx.font = '14px Arial';
  ctx.fillStyle = '#f60';
  ctx.fillRect(125, 1, 62, 20);
  ctx.fillStyle = '#069';
  ctx.fillText('Hello, world! 🌍', 2, 15);
  ctx.fillStyle = 'rgba(102, 204, 0, 0.7)';
  ctx.fillText('Hello, world! 🌍', 4, 17);

  // Extrair dados de pixels e hash
  const data = canvas.toDataURL();
  return hash(data); // ex., "a1b2c3d4..."
}

Métodos de defesa

Método 1: Injetar ruído

// Sobrescrever toDataURL para adicionar ruído aleatório sutil
const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;

HTMLCanvasElement.prototype.toDataURL = function (...args) {
  const ctx = this.getContext('2d');
  if (ctx) {
    // Adicionar pixels aleatórios em posições imperceptíveis
    const imageData = ctx.getImageData(0, 0, this.width, this.height);
    const noise = Math.random() * 0.01;
    imageData.data[0] = Math.min(255, imageData.data[0] + noise);
    ctx.putImageData(imageData, 0, 0);
  }
  return originalToDataURL.apply(this, args);
};

Método 2: Retornar valores fixos

// Todos os canvas retornam a mesma imagem em branco
HTMLCanvasElement.prototype.toDataURL = function () {
  return 'data:image/png;base64,...'; // Imagem em branco fixa
};

2. Impressão digital WebGL

Como funciona

O WebGL expõe informações do renderizador e fabricante da GPU, e diferentes GPUs produzem diferentes resultados de renderização:

function getWebGLFingerprint() {
  const canvas = document.createElement('canvas');
  const gl = canvas.getContext('webgl');

  const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
  const vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);
  const renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);

  // Renderizar cena de teste
  // ... Diferentes GPUs produzem diferentes resultados de pixels

  return { vendor, renderer, renderHash };
}

Informações comumente vazadas

Informação Exemplo
Fabricante da GPU "NVIDIA Corporation", "Intel", "AMD"
Renderizador da GPU "GeForce RTX 4090", "Apple M2"
Tamanho máximo de textura 16384, 8192
Atributos máximos de vértice 16
Lista de extensões suportadas 30+ nomes de extensões

Método de defesa

// Ocultar informações da GPU
const getParameter = WebGLRenderingContext.prototype.getParameter;

WebGLRenderingContext.prototype.getParameter = function (param) {
  if (param === 37445) return 'Intel Inc.';    // UNMASKED_VENDOR
  if (param === 37446) return 'Intel Iris';    // UNMASKED_RENDERER
  return getParameter.call(this, param);
};

3. Impressão digital AudioContext

Como funciona

As unidades de processamento de áudio (DSP) de diferentes dispositivos produzem diferenças sutis ao processar o mesmo sinal:

function getAudioFingerprint() {
  const context = new OfflineAudioContext(1, 44100, 44100);

  const oscillator = context.createOscillator();
  oscillator.type = 'triangle';
  oscillator.frequency.setValueAtTime(10000, context.currentTime);

  const compressor = context.createDynamicsCompressor();
  compressor.threshold.setValueAtTime(-50, context.currentTime);
  compressor.knee.setValueAtTime(40, context.currentTime);
  compressor.ratio.setValueAtTime(12, context.currentTime);

  oscillator.connect(compressor);
  compressor.connect(context.destination);
  oscillator.start(0);

  return context.startRendering().then(buffer => {
    const data = buffer.getChannelData(0);
    return hash(data.slice(4500, 5000));
  });
}

Método de defesa

// Adicionar ruído à saída do AudioContext
const originalStartRendering = OfflineAudioContext.prototype.startRendering;

OfflineAudioContext.prototype.startRendering = function () {
  return originalStartRendering.call(this).then(buffer => {
    const data = buffer.getChannelData(0);
    for (let i = 0; i < data.length; i++) {
      data[i] += (Math.random() - 0.5) * 1e-7;
    }
    return buffer;
  });
};

4. Impressão digital por enumeração de fontes

Como funciona

Ao medir a largura de renderização de diferentes nomes de fontes, é possível determinar quais fontes estão instaladas no sistema do usuário:

function detectFonts() {
  const testFonts = [
    'Arial', 'Helvetica', 'Times New Roman',
    'Courier', 'Verdana', 'Georgia',
    'Comic Sans MS', 'Impact', 'Tahoma',
    'Microsoft YaHei', 'PingFang SC',
  ];

  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');

  const baseFonts = ['monospace', 'serif', 'sans-serif'];
  const results = {};

  for (const font of testFonts) {
    for (const base of baseFonts) {
      ctx.font = `72px ${base}`;
      const baseWidth = ctx.measureText('mmmmmmmmll').width;
      ctx.font = `72px "${font}", ${base}`;
      const testWidth = ctx.measureText('mmmmmmmmll').width;
      if (baseWidth !== testWidth) {
        results[font] = true;
        break;
      }
    }
  }

  return results;
}

Métodos de defesa

A enumeração de fontes é a mais difícil de defender porque aproveita os recursos normais de renderização de texto do navegador. Estratégias principais:

  1. Limitar carregamento de fontes: Permitir apenas fontes do sistema
  2. CSS font-display: block: Atrasar fontes não essenciais
  3. Configurações de privacidade do navegador: privacy.resistFingerprinting do Firefox

5. Análise abrangente de entropia de impressão digital

Dimensão de informação Entropia (bits) Singularidade acumulada
User-Agent ~10 2^10 = 1.024
Resolução de tela ~5 2^15
Fuso horário ~5 2^20
Fontes instaladas ~15 2^35
Canvas ~15 2^50
WebGL ~10 2^60
AudioContext ~5 2^65

2^65 ≈ 3,7 × 10^19, suficiente para identificar exclusivamente cada dispositivo na Terra.


6. Arquitetura de aplicação focada em privacidade

Estratégia de privacidade do ToolsKu

Arquivos do usuário → Processamento local no navegador → Download direto do resultado
         ↑
    Sem trânsito por servidor
    Sem armazenamento de dados
    Sem cookies de rastreamento
    Sem coleta de impressão digital do navegador

Lista de verificação de implementação

Estratégia Implementação Prioridade
Sem rastreamento de terceiros Remover scripts como Google Analytics P0
CSP restringe recursos externos default-src 'self' P0
Sem cookies definidos Site estático não precisa de cookies P0
Referrer-Policy strict-origin-when-cross-origin P1
Permissions-Policy Restringir acesso à API P1
Declaração de privacidade Divulgar claramente o tratamento de dados P1
Arquitetura de processamento local Todo cálculo feito no navegador P0

Configuração de cabeçalhos de segurança HTTP

Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

7. Teste sua própria impressão digital

Recomendamos usar as seguintes ferramentas para testar a singularidade da impressão digital do seu navegador:

  • AmIUnique (amiunique.org): Detecção abrangente de impressão digital
  • BrowserLeaks (browserleaks.com): Análise detalhada de Canvas/WebGL/Audio
  • FingerprintJS (fingerprintjs.com): Demo da biblioteca de impressão digital de código aberto

Dicas para reduzir sua impressão digital:

  1. Use Firefox + privacy.resistFingerprinting = true
  2. Use Tor Browser (impressão digital uniforme)
  3. Use extensões de privacidade (Privacy Badger, uBlock Origin)
  4. Evite instalar fontes raras
  5. Use resoluções e proporções de escala padrão

Experimente estas ferramentas executadas localmente no navegador — nenhum cadastro necessário →

#浏览器指纹#隐私安全#Canvas#WebGL#反追踪