Empreinte

Fingerprinting WebGL : controler l'identite GPU

Comment les chaînes de renderer WebGL et le rendu révèlent l'identité de votre GPU. Découvrez les techniques au niveau du moteur pour contrôler les signaux d'empreinte WebGL.

Documentation

Vous préférez la doc produit maintenue ?

Cet article a une page équivalente dans le centre de documentation. Utilisez les docs pour le flux canonique, les flags à jour et la référence durable.

Introduction

WebGL (Web Graphics Library) permet le rendu 3D accéléré par le matériel dans le navigateur. Les sites web l'utilisent pour les jeux, la visualisation de données, les cartes et le contenu interactif. Mais WebGL expose aussi des informations détaillées sur votre GPU : le nom du fournisseur, la chaîne du renderer, les extensions supportées, les formats de précision, et la sortie pixel par pixel des opérations de rendu. Les systèmes de pistage collectent ces valeurs pour construire une empreinte GPU qui est hautement stable et difficile à modifier. Comme les configurations GPU varient largement entre les appareils, le fingerprinting WebGL peut distinguer les utilisateurs même lorsque les autres signaux sont identiques. Cet article explique comment le fingerprinting WebGL fonctionne, pourquoi les protections courantes échouent, et comment BotBrowser contrôle l'identité GPU au niveau du moteur de rendu.

Impact sur la vie privée

Le fingerprinting WebGL est parmi les signaux de pistage les plus puissants disponibles. Des recherches de l'Inria et KU Leuven ont montré que les chaînes de renderer GPU seules peuvent réduire une population d'utilisateurs à des groupes de moins de 100. Lorsque cela est combiné avec la sortie de rendu (dessiner une scène spécifique et relire les données de pixels), l'unicité augmente dramatiquement.

Une étude de 2020 de l'Université de l'Illinois a démontré que le rendu WebGL produit une sortie spécifique à l'appareil car les GPU implémentent l'arithmétique en virgule flottante, l'échantillonnage de textures et l'exécution de shaders avec de légères différences au niveau matériel. Deux GPU de fabricants différents, même en exécutant le même code de shader, produisent des framebuffers visuellement similaires mais numériquement distincts.

L'ampleur du déploiement est significative. Selon le Princeton Web Transparency and Accountability Project, les scripts de fingerprinting WebGL ont été trouvés sur plus de 7% des 10 000 premiers sites web Alexa. La technique est devenue un composant standard des bibliothèques de pistage commerciales et est utilisée aux côtés du fingerprinting par Canvas, audio et polices pour construire des identifiants composites.

Le fingerprinting WebGL atteint le GPU par trois surfaces indépendantes. Le diagramme ci-dessous montre ce qu'un traceur collecte sur chaque surface et comment les trois flux se combinent en un identifiant composite unique.

Three surfaces, one GPU fingerprint Surface 1: Identity strings WEBGL_debug_renderer_info UNMASKED_VENDOR_WEBGL UNMASKED_RENDERER_WEBGL vendor + GPU model + driver Narrows population to fewer than 100 Surface 2: Parameter queries gl.getParameter(...) MAX_TEXTURE_SIZE shaderPrecisionFormat getSupportedExtensions ~50 numeric properties that vary by GPU class Surface 3: Rendering output readPixels(...) hash draw test scene read framebuffer pixels SHA hash the buffer Pixel-level divergence from float and texture math Composite GPU fingerprint Stable across cookie clears, IP changes, and incognito Defense must address all three surfaces simultaneously. Spoofing one and leaking the other two is itself a signal.

La troisième surface est ce qui rend le fingerprinting WebGL difficile à neutraliser. Les chaînes et les paramètres peuvent être réécrits via JavaScript, mais la sortie de readPixels provient du calcul réel du GPU. Une défense qui retourne une chaîne de fabricant de GPU Mac pendant que le framebuffer porte des motifs de pixels d'un iGPU Intel est détectée par toute vérification croisée qui hache les deux surfaces et compare.

Contexte technique

WebGL expose l'identité GPU à travers plusieurs mécanismes.

Chaînes de renderer et de fournisseur

L'exposition la plus directe provient de l'extension WEBGL_debug_renderer_info :

gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL)
// "ANGLE (NVIDIA GeForce RTX 3080, D3D11)"

gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL)
// "Google Inc. (NVIDIA)"

Ces chaînes révèlent le fabricant du GPU, le modèle et parfois la version du pilote graphique. Elles sont suffisamment uniques pour réduire significativement la population d'utilisateurs.

Sortie de rendu

La sortie de rendu WebGL varie au niveau des pixels en raison des différences matérielles. Un script de fingerprinting pourrait dessiner une scène complexe avec des shaders spécifiques, des dégradés et de la transparence, puis relire le framebuffer avec readPixels(). Les données de pixels résultantes sont hachées pour produire un identifiant stable.

Les sources de variation de rendu incluent :

  • Précision en virgule flottante. Les différents GPU gèrent les opérations float avec un comportement d'arrondi différent, particulièrement dans les fragment shaders.
  • Filtrage de texture. Les implémentations de filtrage bilinéaire et trilinéaire varient entre les fournisseurs.
  • Anti-aliasing. L'implémentation MSAA par défaut diffère entre les architectures GPU.
  • Optimisations au niveau du pilote. Les pilotes GPU appliquent des optimisations spécifiques au fournisseur qui affectent la sortie pixel.

Requêtes de paramètres

WebGL expose des dizaines de paramètres de capacité via getParameter() :

  • MAX_TEXTURE_SIZE, MAX_VIEWPORT_DIMS, MAX_RENDERBUFFER_SIZE
  • MAX_VERTEX_ATTRIBS, MAX_VARYING_VECTORS, MAX_FRAGMENT_UNIFORM_VECTORS
  • ALIASED_LINE_WIDTH_RANGE, ALIASED_POINT_SIZE_RANGE
  • Formats de texture compressée supportés, formats de précision de shaders et extensions

Chacune de ces valeurs reflète les capacités du GPU et contribue à l'empreinte globale.

Extensions WebGL2

WebGL2 ajoute une surface supplémentaire. Les paramètres comme MAX_3D_TEXTURE_SIZE, MAX_ARRAY_TEXTURE_LAYERS et MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS différencient davantage le matériel. La méthode getShaderPrecisionFormat() retourne des détails de précision par type de shader, qui varient entre les familles de GPU.

Le diagramme ci-dessous montre comment un même code de test WebGL produit des empreintes distinctes sur quatre classes de GPU courantes. Chaque ligne est un déploiement réel que les traceurs voient dans leurs données.

Same WebGL code, four GPU classes, four fingerprints GPU class UNMASKED_RENDERER_WEBGL readPixels SHA-256 (prefix) NVIDIA discrete Windows + RTX 3080 ANGLE (NVIDIA, GeForce RTX 3080, D3D11) vendor: Google Inc. (NVIDIA) 2c6d031696... FP16 fast, full extension set Apple Silicon macOS + M2 Pro ANGLE (Apple, ANGLE Metal Renderer: Apple M2 Pro) vendor: Google Inc. (Apple) 9c18bdc539... tile-based deferred rendering Intel iGPU Windows + Iris Xe ANGLE (Intel, Iris Xe Graphics, D3D11) vendor: Google Inc. (Intel) 5c41b9d30f... restricted FP16 ranges Mesa llvmpipe (software) Linux server, no GPU Mesa OpenGL Engine, llvmpipe (LLVM JIT) vendor: Mesa 676363d51d... distinct precision profile Renvoyer les chaînes de la ligne A tout en exécutant les shaders de la ligne D produit une incohérence détectable en une seule vérification croisée.

Approches de protection courantes et leurs limites

Bloquer entièrement WebGL empêche le fingerprinting mais casse une grande partie du web moderne. Les cartes, les visualiseurs de produits 3D, les tableaux de bord de données et les jeux dépendent tous de WebGL. Le désactiver rend votre navigateur moins capable et crée aussi un signal d'empreinte distinctif : l'absence de WebGL est elle-même rare et traçable.

Usurper les chaînes de renderer via une extension de navigateur peut changer ce que UNMASKED_RENDERER_WEBGL retourne, mais cela ne traite qu'une partie de l'empreinte. La sortie de rendu réelle provient toujours de votre vrai GPU. Un site peut dessiner une scène de test, relire les pixels et déterminer votre classe de GPU réelle à partir des caractéristiques de rendu. L'incohérence entre la chaîne rapportée et le comportement de rendu est elle-même un signal fort.

Ajouter du bruit à la sortie de readPixels via l'interception JavaScript modifie les données de framebuffer retournées. Mais l'injection de bruit est détectable : rendre la même scène deux fois devrait produire une sortie identique. Si ce n'est pas le cas, l'injection de bruit est présente. Certaines extensions tentent de mettre en cache et rejouer le bruit, mais cette approche échoue avec les scènes dynamiques et les appels de dessin variés.

Utiliser le rendu logiciel (comme SwiftShader ou Mesa llvmpipe) produit une sortie cohérente entre les matériels mais crée sa propre empreinte distincte. Les renderers logiciels ont un comportement de précision caractéristique et des valeurs de paramètres qui les identifient spécifiquement.

Le défi fondamental est que le fingerprinting WebGL combine les paramètres rapportés avec la sortie de rendu réelle. Une protection efficace doit contrôler les deux simultanément.

L'approche de BotBrowser au niveau du moteur

Le diagramme ci-dessous empile les quatre modèles de défense WebGL courants face au type de vérification croisée qu'effectue un système moderne de fingerprinting. Chaque modèle au-dessus de la couche moteur laisse une incohérence mesurable entre chaînes, paramètres et pixels.

Defense layers and the cross-check that breaks each one 1. Block WebGL entirely getContext('webgl') returns null. Real browsers almost always succeed. Detection: presence of WebGL context is itself a baseline check. 2. Spoof renderer strings via JS shim UNMASKED_RENDERER_WEBGL returns a fake string but readPixels still uses real GPU. Detection: hash a known scene, compare against the table for the claimed GPU class. 3. Inject noise into readPixels output Per-load noise breaks stability: rendering the same scene twice should match. Detection: render the same scene twice and compare. Mismatch flags noise injection. 4. Engine-level rendering control (BotBrowser) Strings, parameters, and pixel output all originate from the same profile-bound pipeline. No JavaScript wrapper to detect. No mismatch between reported GPU and rendered pixels. Same profile + same noise seed reproduces identical hashes across hosts.

BotBrowser contrôle l'identité WebGL au niveau du moteur de rendu Chromium, garantissant que les paramètres rapportés et la sortie de rendu réelle sont tous deux cohérents avec le profil chargé.

Contrôle de l'identité GPU

Lorsqu'un profil d'empreinte est chargé, BotBrowser configure le sous-système WebGL pour rapporter l'identité du GPU profilé :

  • Les chaînes de renderer et de fournisseur correspondent à l'appareil cible. Un profil pour un système avec un Intel UHD 630 rapporte les chaînes exactes de renderer et de fournisseur de ce GPU.
  • Les valeurs de paramètres (taille de texture max, dimensions de viewport, formats de précision, etc.) correspondent toutes aux capacités du GPU profilé. Ce ne sont pas des valeurs aléatoires. Elles correspondent à des configurations matérielles réelles.
  • Les listes d'extensions rapportent exactement les extensions supportées par le GPU profilé. Aucune extension n'est ajoutée ou retirée par rapport au vrai appareil.

Cohérence de la sortie de rendu

Le système de profils de BotBrowser inclut des informations sur les caractéristiques de rendu du GPU cible. Combiné avec le flag --bot-noise-seed, la sortie de rendu devient déterministe et cohérente avec l'appareil profilé. Le moteur applique une variation contrôlée qui produit des données de pixels d'apparence authentique sans exposer votre vrai GPU.

Cela couvre :

  • La précision de la sortie des fragment shaders
  • Le comportement d'échantillonnage de texture
  • Les données de readPixels() pour toute scène dessinée
  • Les résultats de getShaderPrecisionFormat()
  • Les opérations de mélange du framebuffer

Couverture WebGL2

Les mêmes contrôles s'appliquent à WebGL2. Les paramètres, extensions et comportements de rendu sont tous dérivés du profil. Il n'y a aucune lacune entre la protection WebGL1 et WebGL2.

Cohérence inter-API

BotBrowser garantit que les données WebGL s'alignent avec les autres signaux du profil. Le GPU rapporté par WebGL correspond à ce qui apparaît dans navigator.userAgentData, ce que le rendu Canvas produit, et ce que WebGPU rapporte (s'il est activé). Cette cohérence inter-API est critique car les systèmes de pistage vérifient couramment les signaux liés au GPU entre plusieurs API.

Configuration et utilisation

Protection WebGL de base

Chargez un profil pour configurer tous les paramètres WebGL :

chrome --bot-profile="/path/to/profile.enc" \
       --user-data-dir="$(mktemp -d)"

Substitution de la configuration WebGL

Contrôlez le comportement WebGL indépendamment :

# Utiliser les paramètres WebGL du profil (par défaut)
chrome --bot-profile="/path/to/profile.enc" \
       --bot-config-webgl=profile

# Utiliser le vrai GPU du système (pas de protection WebGL)
chrome --bot-profile="/path/to/profile.enc" \
       --bot-config-webgl=real

# Désactiver entièrement WebGL
chrome --bot-profile="/path/to/profile.enc" \
       --bot-config-webgl=disabled

Rendu déterministe avec graine de bruit

Pour des empreintes WebGL reproductibles :

chrome --bot-profile="/path/to/profile.enc" \
       --bot-noise-seed=42 \
       --user-data-dir="$(mktemp -d)"

Intégration Playwright

const { chromium } = require('playwright');

const browser = await chromium.launch({
  executablePath: '/path/to/botbrowser/chrome',
  args: [
    '--bot-profile=/path/to/profile.enc',
    '--bot-config-webgl=profile',
    '--bot-noise-seed=42'
  ]
});

const page = await browser.newPage();
await page.goto('https://example.com');

Intégration Puppeteer

const puppeteer = require('puppeteer');

const browser = await puppeteer.launch({
  executablePath: '/path/to/botbrowser/chrome',
  defaultViewport: null,
  args: [
    '--bot-profile=/path/to/profile.enc',
    '--bot-config-webgl=profile',
    '--bot-noise-seed=42'
  ]
});

const page = await browser.newPage();
await page.goto('https://example.com');

Contrôle séparé du bruit d'image WebGL

# Désactiver le bruit d'image WebGL tout en conservant l'autre protection WebGL
chrome --bot-profile="/path/to/profile.enc" \
       --bot-config-noise-webgl-image=false

Vérification

Pour vérifier que la protection WebGL fonctionne :

Vérification de la chaîne de renderer. Ouvrez la console du navigateur et interrogez UNMASKED_RENDERER_WEBGL. La valeur devrait correspondre au GPU cible du profil, pas à votre matériel réel.

Cohérence des paramètres. Vérifiez plusieurs paramètres WebGL (MAX_TEXTURE_SIZE, formats de précision, liste d'extensions) et confirmez qu'ils correspondent aux valeurs attendues pour le GPU profilé.

Stabilité inter-sessions. Exécutez la même routine de fingerprinting WebGL dans deux sessions avec le même profil et la même graine de bruit. Les résultats devraient être identiques.

Stabilité inter-machines. Exécutez le test sur du matériel différent avec le même profil et la même graine. L'empreinte WebGL devrait correspondre.

Visitez BrowserLeaks, CreepJS ou des sites de test d'empreinte similaires pour comparer votre sortie WebGL avec les valeurs attendues de votre profil.

La matrice de vérification ci-dessous montre à quoi ressemble le succès sur trois hôtes exécutant le même profil. Chaînes UNMASKED identiques, hachages readPixels identiques pour WebGL1 et WebGL2, liste d'extensions identique, quel que soit le matériel hôte.

Cross-platform verification: same profile, identical WebGL signature Windows host running BotBrowser profile = mac_arm64.enc seed = 100 UNMASKED_RENDERER ANGLE Metal · M2 Pro vendor: Apple webgl1: 0f9829ee244b webgl2: b879347569e8 macOS host running BotBrowser profile = mac_arm64.enc seed = 100 UNMASKED_RENDERER ANGLE Metal · M2 Pro vendor: Apple webgl1: 0f9829ee244b webgl2: b879347569e8 Linux host (Xvfb) running BotBrowser profile = mac_arm64.enc seed = 100 UNMASKED_RENDERER ANGLE Metal · M2 Pro vendor: Apple webgl1: 0f9829ee244b webgl2: b879347569e8 Même profil + même graine = chaînes UNMASKED identiques, hash WebGL1 identique, hash WebGL2 identique. Chaînes et pixels restent alignés.

Bonnes pratiques

  • Utilisez --bot-config-webgl=profile (par défaut). Cela garantit que tous les paramètres WebGL proviennent du profil. Ne passez à real que si vous avez spécifiquement besoin de l'accès natif au GPU.
  • Combinez avec --bot-noise-seed pour une sortie déterministe. Sans graine, le bruit de rendu WebGL varie entre les sessions. Une graine fixe garantit la reproductibilité.
  • Faites correspondre les paramètres WebGL et WebGPU. Si votre profil a des données WebGL et WebGPU, gardez les deux à profile pour maintenir la cohérence. Une incohérence entre le GPU rapporté par WebGL et WebGPU est une incohérence détectable.
  • Ne substituez pas manuellement les chaînes de renderer. BotBrowser gère cela via le profil. Définir manuellement les chaînes de renderer sans faire correspondre le comportement de rendu crée des incohérences.
  • Testez avec des sites de vérification d'empreinte. Vérifiez que votre empreinte WebGL correspond aux attentes avant de déployer en production.

FAQ

Q : Le fingerprinting WebGL fonctionne-t-il sans l'extension WEBGL_debug_renderer_info ? R : Partiellement. Sans l'extension, les chaînes de renderer et de fournisseur ne sont pas disponibles, mais la sortie de rendu, les valeurs de paramètres et les formats de précision varient toujours par GPU. L'empreinte basée sur le rendu seule est souvent suffisante pour réduire la population d'utilisateurs.

Q : Puis-je utiliser BotBrowser avec des applications WebGL intensives comme les jeux 3D ? R : Oui. Le contrôle WebGL de BotBrowser opère au niveau de l'identité et de l'empreinte. Les performances de rendu viennent de votre vrai GPU. Les jeux et applications 3D fonctionnent normalement.

Q : La protection WebGL affecte-t-elle le fingerprinting Canvas ? R : Canvas 2D et WebGL utilisent des chemins de rendu différents, mais BotBrowser contrôle les deux via le profil. Ils produisent des résultats cohérents qui s'alignent avec le même appareil profilé.

Q : Que se passe-t-il si un site demande des extensions WebGL absentes de mon profil ? R : BotBrowser rapporte uniquement les extensions listées dans le profil. Les demandes pour des extensions non supportées retournent null, cohérent avec le comportement du GPU profilé.

Q : WebGL2 est-il protégé séparément de WebGL1 ? R : Les deux sont contrôlés par le même profil et la même configuration. Le flag --bot-config-webgl s'applique aux contextes WebGL1 et WebGL2.

Q : Comment BotBrowser gère-t-il WebGL dans les Web Workers ? R : Les contextes WebGL OffscreenCanvas dans les workers sont soumis aux mêmes contrôles au niveau du moteur que les contextes du thread principal. L'empreinte est cohérente dans les deux cas.

Résumé

Le fingerprinting WebGL combine les chaînes d'identité GPU, les paramètres de capacité et la sortie de rendu au niveau des pixels pour créer un signal de pistage puissant. Parce qu'il atteint la couche matérielle, les protections basées sur JavaScript ne peuvent pas le traiter complètement. BotBrowser contrôle l'identité et le rendu WebGL au niveau du moteur Chromium, garantissant que chaque surface d'API retourne des valeurs cohérentes avec le profil d'empreinte chargé. Combiné avec --bot-noise-seed pour une sortie déterministe et --bot-config-webgl pour un contrôle explicite, BotBrowser fournit une protection complète des empreintes WebGL.

Pour les sujets connexes, voir What is Browser Fingerprinting, WebGPU Fingerprint Protection, Canvas Fingerprinting, et Audio Fingerprint Protection.

#Webgl#fingerprinting#Gpu#Privacy#Webgl2

Faites passer BotBrowser de la recherche à la production

Utilisez ces guides pour comprendre le modèle, puis passez à la validation multi-plateforme, aux contextes isolés et au déploiement navigateur prêt pour l'échelle.