Panoramica
Il fingerprinting Canvas sfrutta le sottili differenze nel modo in cui hardware e software renderizzano la grafica. Queste differenze derivano da:
- Modello GPU e versione del driver
- Rendering dei font del sistema operativo (anti-aliasing, hinting, rendering subpixel)
- Motore di rendering del browser
- Font di sistema installati
Canvas Fingerprinting
Meccanismo
- Il sito disegna forme e testo su un elemento HTML5
<canvas> - Chiama
canvas.toDataURL()per estrarre i dati dei pixel come base64 - Applica un hash al risultato (MD5, SHA-1, o hash personalizzato)
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
ctx.font = '14px Arial'
ctx.fillStyle = '#f60'
ctx.fillRect(125, 1, 62, 20)
ctx.fillStyle = '#069'
ctx.fillText('BrowserLeaks,com <canvas> 1.0', 2, 15)
const fingerprint = canvas.toDataURL()
const hash = md5(fingerprint) // unico per dispositivo
Fonti di Entropia
| Fonte | Variabilità |
|---|---|
| Rendering font (anti-aliasing, hinting) | Alta |
| Ordine rendering subpixel (RGB vs BGR) | Media |
| Rasterizzazione GPU delle forme | Media |
| Conversione spazio colore | Bassa |
WebGL Fingerprinting
Meccanismo
WebGL espone la GPU direttamente tramite:
const gl = canvas.getContext('webgl')
const debugInfo = gl.getExtension('WEBGL_debug_renderer_info')
const renderer = debugInfo.UNMASKED_RENDERER_WEBGL
// es. "NVIDIA GeForce RTX 3080/PCIe/SSE2"
const vendor = debugInfo.UNMASKED_VENDOR_WEBGL
// es. "NVIDIA Corporation"
Inoltre, il rendering di scene 3D produce output pixel specifici dell'hardware.
Segnali
UNMASKED_RENDERER_WEBGL: modello esatto della GPUUNMASKED_VENDOR_WEBGL: produttore GPU- Precisione shader WebGL
MAX_TEXTURE_SIZE,MAX_VERTEX_ATTRIBS, ecc.- Rendering scena 3D (hash dei pixel)
WebGPU Fingerprinting
WebGPU (il successore di WebGL) espone informazioni ancora più granulari:
const adapter = await navigator.gpu.requestAdapter()
const info = await adapter.requestAdapterInfo()
// { vendor: "nvidia", architecture: "ampere", device: "..." }
Segnali
adapterInfo.vendoradapterInfo.architectureadapterInfo.device- Set di funzionalità (quali funzionalità GPU sono supportate)
Perché lo Spoofing a Livello di Proxy è Difficile
Il rendering Canvas/WebGL/WebGPU avviene sulla GPU locale. Il proxy vede solo il traffico di rete. Quando i dati raggiungono il proxy, il rendering è già completo.
Approcci di mitigazione possibili:
Bloccare l'API: Far sì che WebGL restituisca null, canvas generi un errore. Problema: rilevabile come segnale ("WebGL bloccato" è di per sé un tratto di fingerprint).
-
Iniettare rumore JS: CanvasBlocker (Firefox) randomizza l'output canvas iniettando un pixel casuale prima di
toDataURL(). Problema: se il sito legge canvas 3 volte e ottiene 3 hash diversi, rileva la manomissione. Richiede anche rumore a frequenza costante. -
Override ImageData tramite Proxy: Sovrascrivere
CanvasRenderingContext2D.prototype.getImageDatatramite JS iniettato per restituire dati generici. Problema: funziona solo sugetImageData, non sutoDataURL. Percorsi multipli per estrarre pixel.
Rendering GPU Software (SwiftShader/Lavapipe): Sostituire il rendering GPU con un renderer deterministico basato su CPU. Problema: costo prestazionale massiccio, nessuna accelerazione 3D.
Formule
Entropia del Fingerprint Canvas
Dove è la probabilità di un dato hash su diversi dispositivi.
Entropia stimata: ~5-7 bit (può distinguere ~32-128 dispositivi).
Probabilità di Unicità
Dove è la dimensione della popolazione e è il numero di output canvas distinti nel campione.
Conclusioni
- Il fingerprinting Canvas/WebGL non può essere completamente falsificato a livello di proxy
- L'iniezione di rumore tramite JS è una mitigazione parziale ma rilevabile
- Bloccare queste API è rilevabile e diventa esso stesso un segnale
- L'unica soluzione quasi completa è l'approccio di Tor Browser (normalizzare tutti gli utenti con output identico)
- Per Obscura: l'approccio migliore è JS iniettato che aggiunge rumore coerente + blocca
WEBGL_debug_renderer_info