Saltar al contenido principal
it/blog/obscura/research/web-fingerprinting/

obscura/research/web-fingerprinting

7 min di lettura

Panoramica

Segnali derivati dalle funzionalità della piattaforma web, capacità CSS, font e altre caratteristiche del browser.


1. Fingerprinting dei Font

Meccanismo

I font vengono enumerati tramite diverse tecniche:

  1. Misurazione CSS @font-face: Crea testo, misura la sua larghezza con un font noto, poi prova a caricare un font di sistema. Se la larghezza cambia, il font esiste.

  2. Canvas measureText: Approccio simile che utilizza canvas.

  3. document.fonts.check(): API moderna per verificare la disponibilità dei font.


  4. Enumerazione basata su Flash (legacy, ancora usata): Flash può elencare tutti i font installati.


Esempio di Codice

// Rilevamento font basato su misurazione
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
const text = 'mmmmmmmmmmlli'

function detectFont(font) {
  ctx.font = `72px ${font}, monospace`
  return ctx.measureText(text).width
}

// Confronta la larghezza con la baseline monospace per rilevare

Entropia

L'elenco dei font varia ampiamente:

Piattaforma Font Tipici Unicità
Windows 11 stock ~80 font Media
macOS Ventura+ ~120 font Media
Linux (distro varia) 10-500 font Molto Alta
Font personalizzati installati Qualsiasi Molto Alta

Mitigazione al Proxy

// Sovrascrivi la misurazione dei font per restituire valori coerenti
const originalMeasureText = CanvasRenderingContext2D.prototype.measureText
CanvasRenderingContext2D.prototype.measureText = function(text) {
  const result = originalMeasureText.call(this, text)
  // Arrotonda la larghezza per ridurre la precisione del rilevamento font
  result.width = Math.round(result.width / 10) * 10
  return result
}

Limitazione: Il rilevamento dei font è solo ridotto, non eliminato.


2. Supporto Funzionalità Browser (25+ vettori binari)

Meccanismo

Ogni browser supporta un sottoinsieme diverso di API web e funzionalità CSS. Collettivamente, questo crea un fingerprint browser+versione.

Funzionalità ad Alta Entropia

Funzionalità Chrome Firefox Safari
WebGL
WebGPU Sì (flag) No No
WebUSB No No
Web Bluetooth No No
Web NFC Android No No
Web Authentication
Web Assembly
Service Workers
Battery API No No
Speech Synthesis
GamePad API Sì (parziale)
WebRTC
CSS Grid
CSS backdrop-filter
CSS Container Queries

Entropia

Ogni funzionalità aggiunge ~1 bit. Con ~100 funzionalità testate, il massimo teorico è 100 bit, ma le funzionalità sono altamente correlate (entropia minima oltre la famiglia e versione del browser).

Entropia effettiva: ~8-12 bit (~256-4096 combinazioni).

Mitigazione

Non può essere fatto a livello di proxy: queste sono capacità intrinseche del browser. Il rilevamento delle funzionalità viene eseguito in JS prima che qualsiasi script iniettato possa essere eseguito (e anche se sovrascritto, il browser riporta comunque le capacità effettive da qualche parte).


3. Fingerprinting tramite Media Query CSS

Meccanismo

Le query CSS @media possono ricavare forzatamente le dimensioni dello schermo, DPI, profondità colore e altre proprietà senza JS:

@media (width: 1920px) { body::after { content: '1920' } }
@media (height: 1080px) { body::after { content: '1080' } }
@media (resolution: 1.5dppx) { body::after { content: '1.5' } }
@media (prefers-color-scheme: dark) { ... }
@media (prefers-reduced-motion: no-preference) { ... }
@media (hover: hover) { ... }
@media (pointer: fine) { ... }

Sfida per il Proxy

Il CSS viene eseguito prima di qualsiasi iniezione JS. Il proxy può:

  1. Analizzare il CSS nell'HTML della risposta e modificare le media query
  2. O fare affidamento sul fatto che i probe CSS-only devono esfiltrare dati (che richiede JS o una richiesta di rete)

Mitigazione reale: Blocca il percorso di esfiltrazione (JS o caricamento immagini) piuttosto che falsificare i valori CSS.

Elenco Media Query

Query Valori Informazioni Rivelate
width px Larghezza schermo
height px Altezza schermo
aspect-ratio ratio Rapporto schermo
resolution dppx Densità pixel
color bit Profondità colore
color-gamut srgb/p3/rec2020 Spazio colore
prefers-color-scheme light/dark Tema OS
prefers-reduced-motion no-preference/reduce Impostazione OS
prefers-contrast no-preference/more/less Impostazione OS
prefers-reduced-transparency no-preference/reduce Impostazione OS
hover none/hover Dispositivo di input
pointer none/coarse/fine Dispositivo di input
any-hover none/hover Qualsiasi input
any-pointer none/coarse/fine Qualsiasi input
display-mode fullscreen/standalone Modalità PWA
prefers-color-gamut srgb/p3 Gamut display
dynamic-range standard/high Supporto HDR
inverted-colors none/inverted Accessibilità OS
monochrome bit Display monocromatico
forced-colors none/active Accessibilità
prefers-reduced-data no-preference/reduce Risparmio dati

4. Fingerprinting ClientRects

Meccanismo

Element.getClientRects() restituisce valori leggermente diversi a seconda del SO, del browser e del rendering dei font:

const span = document.createElement('span')
span.textContent = 'mmmmmmmmmmlli'
document.body.appendChild(span)
const rects = span.getClientRects()
// rects[0].width varia per SO/browser/font

Mitigazione

Element.prototype.getClientRects = function() {
  const rects = Element.prototype.__proto__.getClientRects.call(this)
  return Array.from(rects).map(r => ({
    ...r,
    width: Math.round(r.width / 10) * 10,
    height: Math.round(r.height / 10) * 10
  }))
}

5. Fingerprint Web Audio API

Vedi audio-fingerprinting.md per i dettagli.


6. Fingerprinting WebGPU

WebGPU fornisce informazioni strutturate sul dispositivo non precedentemente disponibili:

const adapter = await navigator.gpu.requestAdapter()
const info = await adapter.requestAdapterInfo()
// { vendor: "nvidia", architecture: "ampere", device: "..." }

// I limiti dell'adattatore espongono capacità GPU specifiche
const limits = adapter.limits
// maxTextureDimension2D, maxStorageBufferBindingSize, ecc.

// Set di funzionalità
adapter.features.has('texture-compression-bc')
adapter.features.has('shader-f16')

Dati Esposti

Campo Esempio Identificabilità
vendor "nvidia", "apple", "amd", "intel" Bassa (4-5 valori)
architecture "ampere", "rdna2", "tigerlake" Media
device "integrated-graphics", "Apple M3" Media
driver "460.32.03" Alta
backend "Metal", "Vulkan", "D3D12" Bassa
type "discrete-gpu", "integrated-gpu", "cpu" Bassa
memoryHeaps dimensione e conteggio Alta
limits 50+ valori di capacità Molto Alta

Mitigazione

// Blocca le informazioni dell'adattatore WebGPU
navigator.gpu.requestAdapter = async function() {
  return null  // o restituisci un adattatore fittizio minimo
}

Costo: Blocca WebGPU completamente, rompendo alcune app.


7. Persistenza Service Worker

Meccanismo

I Service Workers possono essere usati per identificare gli utenti tra sessioni:

// Rileva se un SW è installato
navigator.serviceWorker.getRegistrations().then(regs => {
  if (regs.length > 0) console.log('SW trovato')
})

Mitigazione

navigator.serviceWorker.getRegistrations =
  async () => []

8. Fingerprint Estensioni WebGL

WebGL espone un elenco di estensioni supportate che varia per GPU, driver e browser:

Tipo Estensione Conteggio Esempio
WebGL standard ~30 OES_texture_float
WEBGL_* ~15 WEBGL_debug_renderer_info
EXT_* ~15 EXT_texture_filter_anisotropic
Specifiche del browser ~5 MOZ_WEBGL_*

Entropia: L'insieme e il conteggio esatti delle estensioni crea un hash.

Mitigazione:

const originalGetExtension = WebGLRenderingContext.prototype.getExtension
WebGLRenderingContext.prototype.getExtension = function(name) {
  if (name === 'WEBGL_debug_renderer_info') return null
  if (name.startsWith('MOZ_')) return null
  return originalGetExtension.call(this, name)
}

Conclusioni per Obscura

Vettore Controllo Proxy Strategia di Mitigazione
Enumerazione font Parziale Arrotonda misurazioni, blocca Flash
Supporto funzionalità Nessuno Accetta: inerente al browser
Media query CSS Parziale Blocca esfiltrazione (DNS/network)
ClientRects Parziale Arrotonda valori tramite iniezione JS
WebGPU Parziale Blocca informazioni adattatore
Service Workers Parziale Sovrascrivi API di registrazione
Estensioni WebGL Parziale Filtra elenco estensioni