Отпечатки

Фингерпринтинг WebGL: контроль идентичности GPU

Как строки рендерера WebGL и вывод рендеринга раскрывают идентичность вашего GPU. Техники контроля сигналов отпечатка WebGL на уровне движка.

Документация

Нужна поддерживаемая продуктовая документация?

У этой статьи есть соответствующая страница в центре документации. Используйте docs для каноничного сценария настройки, актуальных флагов и долгосрочной справки.

Введение

WebGL (Web Graphics Library) обеспечивает аппаратно-ускоренный 3D-рендеринг внутри браузера. Веб-сайты используют его для игр, визуализации данных, карт и интерактивного контента. Однако WebGL также раскрывает подробную информацию о вашем GPU: название производителя, строку рендерера, поддерживаемые расширения, форматы точности и попиксельный вывод операций рендеринга. Системы отслеживания собирают эти значения для построения GPU-отпечатка, который является высокостабильным и трудноизменяемым. Поскольку конфигурации GPU сильно различаются между устройствами, фингерпринтинг WebGL может различать пользователей даже при идентичных других сигналах. В этой статье объясняется, как работает фингерпринтинг WebGL, почему распространённые защиты недостаточны и как BotBrowser контролирует GPU-идентичность на уровне движка рендеринга.

Влияние на приватность

Фингерпринтинг WebGL является одним из наиболее мощных доступных сигналов отслеживания. Исследование Inria и KU Leuven показало, что одни строки рендерера GPU могут сузить популяцию пользователей до групп менее 100 человек. В сочетании с выводом рендеринга (отрисовка конкретной сцены и считывание пиксельных данных) уникальность значительно возрастает.

Исследование 2020 года из Университета Иллинойса продемонстрировало, что WebGL-рендеринг производит специфичный для устройства вывод, поскольку GPU реализуют арифметику с плавающей точкой, сэмплирование текстур и выполнение шейдеров с незначительными различиями на аппаратном уровне. Два GPU от разных производителей, даже при запуске одного и того же кода шейдера, производят визуально похожие, но численно различные фреймбуферы.

Масштаб применения значителен. По данным проекта Princeton Web Transparency and Accountability Project, скрипты фингерпринтинга WebGL были обнаружены на более чем 7% сайтов из топ-10 000 Alexa. Техника стала стандартным компонентом коммерческих библиотек отслеживания и используется наряду с фингерпринтингом Canvas, аудио и шрифтов для построения составных идентификаторов.

Фингерпринтинг WebGL добирается до GPU через три независимые поверхности. Диаграмма ниже показывает, что трекер собирает с каждой поверхности и как три потока сводятся в один составной идентификатор.

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.

Третья поверхность это то, что делает фингерпринтинг WebGL трудным для нейтрализации. Строки и параметры можно переписать через JavaScript, но вывод readPixels исходит от реального вычисления GPU. Защита, которая возвращает строку производителя GPU Mac, пока framebuffer несёт пиксельные паттерны iGPU Intel, обнаруживается любой перекрёстной проверкой, которая хеширует обе поверхности и сравнивает результат.

Техническая основа

WebGL раскрывает идентичность GPU через несколько механизмов.

Строки рендерера и производителя

Наиболее прямое раскрытие происходит через расширение 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)"

Эти строки раскрывают производителя GPU, модель и иногда версию графического драйвера. Они достаточно уникальны, чтобы значительно сузить популяцию пользователей.

Вывод рендеринга

Вывод WebGL-рендеринга различается на пиксельном уровне из-за аппаратных различий. Скрипт фингерпринтинга может отрисовать сложную сцену с определёнными шейдерами, градиентами и прозрачностью, затем считать фреймбуфер через readPixels(). Полученные пиксельные данные хешируются для создания стабильного идентификатора.

Источники вариации рендеринга включают:

  • Точность вычислений с плавающей точкой. Разные GPU выполняют float-операции с разным поведением округления, особенно во фрагментных шейдерах.
  • Фильтрация текстур. Реализации билинейной и трилинейной фильтрации различаются между производителями.
  • Сглаживание. Реализация MSAA по умолчанию различается между архитектурами GPU.
  • Оптимизации на уровне драйвера. GPU-драйверы применяют вендор-специфичные оптимизации, влияющие на пиксельный вывод.

Запросы параметров

WebGL раскрывает десятки параметров возможностей через 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
  • Поддерживаемые форматы сжатия текстур, форматы точности шейдеров и расширения

Каждое из этих значений отражает возможности GPU и вносит вклад в общий отпечаток.

Расширения WebGL2

WebGL2 добавляет дополнительную поверхность. Параметры вроде MAX_3D_TEXTURE_SIZE, MAX_ARRAY_TEXTURE_LAYERS и MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS дополнительно дифференцируют оборудование. Метод getShaderPrecisionFormat() возвращает детали точности для каждого типа шейдера, которые различаются между семействами GPU.

Диаграмма ниже показывает, как один и тот же тестовый код WebGL производит разные отпечатки на четырёх распространённых классах GPU. Каждая строка представляет реальное развёртывание, которое трекеры видят в своих базах данных.

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 Возврат строк из строки A при выполнении шейдеров из строки D создаёт расхождение, которое детектируется одной перекрёстной проверкой.

Распространённые подходы защиты и их ограничения

Полная блокировка WebGL предотвращает фингерпринтинг, но нарушает работу значительной части современного веба. Карты, 3D-просмотрщики продуктов, информационные панели и игры зависят от WebGL. Его отключение делает ваш браузер менее функциональным и также создаёт характерный сигнал отпечатка: отсутствие WebGL само по себе необычно и отслеживаемо.

Подмена строк рендерера через расширение браузера может изменить то, что возвращает UNMASKED_RENDERER_WEBGL, но это затрагивает только одну часть отпечатка. Фактический вывод рендеринга по-прежнему приходит от вашего реального GPU. Сайт может отрисовать тестовую сцену, считать пиксели и определить ваш реальный класс GPU по характеристикам рендеринга. Несоответствие между заявленной строкой и поведением рендеринга само по себе является сильным сигналом.

Добавление шума к выводу readPixels через JavaScript-перехват модифицирует возвращаемые данные фреймбуфера. Но инъекция шума обнаруживаема: рендеринг одной и той же сцены дважды должен давать идентичный вывод. Если нет, значит, присутствует инъекция шума. Некоторые расширения пытаются кешировать и воспроизводить шум, но этот подход нарушается при динамических сценах и разнообразных вызовах отрисовки.

Использование программного рендеринга (вроде SwiftShader или Mesa llvmpipe) даёт согласованный вывод на разном оборудовании, но создаёт собственный характерный отпечаток. Программные рендереры имеют характерное поведение точности и значения параметров, которые идентифицируют их специфически.

Основная сложность в том, что фингерпринтинг WebGL комбинирует заявленные параметры с реальным выводом рендеринга. Эффективная защита должна контролировать оба одновременно.

Подход BotBrowser на уровне движка

Диаграмма ниже сопоставляет четыре распространённые модели защиты WebGL с типом перекрёстной проверки, которую выполняет современный движок фингерпринтинга. Каждая модель над уровнем движка оставляет измеримое расхождение между строками, параметрами и пикселями.

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 контролирует идентичность WebGL на уровне движка рендеринга Chromium, обеспечивая согласованность заявленных параметров и реального вывода рендеринга с загруженным профилем.

Контроль GPU-идентичности

При загрузке профиля отпечатка BotBrowser настраивает подсистему WebGL для сообщения идентичности GPU из профиля:

  • Строки рендерера и производителя соответствуют целевому устройству. Профиль для системы с Intel UHD 630 сообщает точные строки рендерера и производителя этого GPU.
  • Значения параметров (максимальный размер текстуры, размеры viewport, форматы точности и т.д.) все соответствуют возможностям GPU из профиля. Это не случайные значения. Они соответствуют реальным аппаратным конфигурациям.
  • Списки расширений сообщают именно те расширения, которые поддерживает GPU из профиля. Никакие расширения не добавляются и не удаляются по сравнению с реальным устройством.

Согласованность вывода рендеринга

Система профилей BotBrowser включает информацию о характеристиках рендеринга целевого GPU. В сочетании с флагом --bot-noise-seed вывод рендеринга становится детерминированным и согласованным с профилированным устройством. Движок применяет контролируемую вариацию, которая производит аутентично выглядящие пиксельные данные без раскрытия вашего реального GPU.

Это покрывает:

  • Точность вывода фрагментных шейдеров
  • Поведение сэмплирования текстур
  • Данные readPixels() для любой отрисованной сцены
  • Результаты getShaderPrecisionFormat()
  • Операции смешивания фреймбуфера

Покрытие WebGL2

Те же элементы управления применяются к WebGL2. Параметры, расширения и поведение рендеринга - всё выводится из профиля. Нет разрыва между защитой WebGL1 и WebGL2.

Кросс-API согласованность

BotBrowser обеспечивает согласованность данных WebGL с другими сигналами профиля. GPU, о котором сообщает WebGL, совпадает с тем, что отображается в navigator.userAgentData, что производит рендеринг Canvas и что сообщает WebGPU (при включении). Эта кросс-API согласованность критична, поскольку системы отслеживания обычно перекрёстно проверяют сигналы, связанные с GPU, через несколько API.

Конфигурация и использование

Базовая защита WebGL

Загрузите профиль для настройки всех параметров WebGL:

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

Переопределение конфигурации WebGL

Управление поведением WebGL независимо:

# Использование настроек WebGL из профиля (по умолчанию)
chrome --bot-profile="/path/to/profile.enc" \
       --bot-config-webgl=profile

# Использование реального системного GPU (без защиты WebGL)
chrome --bot-profile="/path/to/profile.enc" \
       --bot-config-webgl=real

# Полное отключение WebGL
chrome --bot-profile="/path/to/profile.enc" \
       --bot-config-webgl=disabled

Детерминированный рендеринг с seed-шума

Для воспроизводимых отпечатков WebGL:

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

Интеграция с 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');

Интеграция с 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');

Отдельный контроль шума WebGL-изображений

# Отключение шума WebGL-изображений при сохранении остальной защиты WebGL
chrome --bot-profile="/path/to/profile.enc" \
       --bot-config-noise-webgl-image=false

Верификация

Для проверки работоспособности защиты WebGL:

Проверка строки рендерера. Откройте консоль браузера и запросите UNMASKED_RENDERER_WEBGL. Значение должно соответствовать целевому GPU профиля, а не вашему реальному оборудованию.

Согласованность параметров. Проверьте несколько параметров WebGL (MAX_TEXTURE_SIZE, форматы точности, список расширений) и убедитесь, что они соответствуют ожидаемым значениям для GPU из профиля.

Стабильность между сессиями. Запустите одну и ту же процедуру фингерпринтинга WebGL в двух сессиях с одним профилем и seed-шума. Результаты должны быть идентичны.

Стабильность между машинами. Запустите тест на разном оборудовании с одним профилем и seed. Отпечаток WebGL должен совпадать.

Посетите BrowserLeaks, CreepJS или аналогичные сайты тестирования отпечатков для сравнения вашего вывода WebGL с ожидаемыми значениями профиля.

Матрица верификации ниже показывает, как выглядит успех на трёх хостах с одним и тем же профилем. Идентичные строки UNMASKED, идентичные хэши readPixels для WebGL1 и WebGL2, идентичный список расширений, независимо от оборудования хоста.

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 Один профиль + одно семя = идентичные строки UNMASKED, идентичный хэш WebGL1, идентичный хэш WebGL2. Строки и пиксели остаются согласованными.

Лучшие практики

  • Используйте --bot-config-webgl=profile (по умолчанию). Это обеспечивает получение всех параметров WebGL из профиля. Переключайтесь на real только если вам специально нужен доступ к нативному GPU.
  • Комбинируйте с --bot-noise-seed для детерминированного вывода. Без seed шум рендеринга WebGL варьируется между сессиями. Фиксированный seed обеспечивает воспроизводимость.
  • Согласовывайте настройки WebGL и WebGPU. Если ваш профиль содержит данные и WebGL, и WebGPU, держите оба в режиме profile для поддержания согласованности. Несоответствие между GPU, о котором сообщают WebGL и WebGPU, является обнаруживаемым несоответствием.
  • Не переопределяйте строки рендерера вручную. BotBrowser обрабатывает это через профиль. Ручная установка строк рендерера без согласования поведения рендеринга создаёт несоответствия.
  • Тестируйте на сайтах проверки отпечатков. Проверьте, что ваш отпечаток WebGL соответствует ожиданиям, перед развёртыванием в продакшен.

FAQ

В: Работает ли фингерпринтинг WebGL без расширения WEBGL_debug_renderer_info? О: Частично. Без расширения строки рендерера и производителя недоступны, но вывод рендеринга, значения параметров и форматы точности по-прежнему варьируются в зависимости от GPU. Отпечатка на основе рендеринга часто достаточно для сужения популяции пользователей.

В: Можно ли использовать BotBrowser с WebGL-интенсивными приложениями вроде 3D-игр? О: Да. Контроль WebGL BotBrowser работает на уровне идентичности и отпечатка. Производительность рендеринга обеспечивается вашим реальным GPU. Игры и 3D-приложения работают нормально.

В: Влияет ли защита WebGL на фингерпринтинг Canvas? О: Canvas 2D и WebGL используют разные пути рендеринга, но BotBrowser контролирует оба через профиль. Они производят согласованные результаты, соответствующие одному профилированному устройству.

В: Что происходит, если сайт запрашивает расширения WebGL, отсутствующие в моём профиле? О: BotBrowser сообщает только расширения, указанные в профиле. Запросы неподдерживаемых расширений возвращают null, что согласовано с поведением GPU из профиля.

В: Защищается ли WebGL2 отдельно от WebGL1? О: Оба контролируются одним профилем и конфигурацией. Флаг --bot-config-webgl применяется как к контекстам WebGL1, так и к WebGL2.

В: Как BotBrowser обрабатывает WebGL в Web Workers? О: Контексты WebGL OffscreenCanvas в workers подчиняются тем же элементам управления на уровне движка, что и контексты основного потока. Отпечаток согласован в обоих случаях.

Итоги

Фингерпринтинг WebGL объединяет строки идентичности GPU, параметры возможностей и попиксельный вывод рендеринга для создания мощного сигнала отслеживания. Поскольку он проникает на аппаратный уровень, защиты на основе JavaScript не могут полностью его адресовать. BotBrowser контролирует идентичность и рендеринг WebGL на уровне движка Chromium, обеспечивая, что каждая поверхность API возвращает значения, согласованные с загруженным профилем отпечатка. В сочетании с --bot-noise-seed для детерминированного вывода и --bot-config-webgl для явного контроля BotBrowser обеспечивает полную защиту отпечатка WebGL.

По связанным темам смотрите Что такое фингерпринтинг браузера, Защита отпечатка WebGPU, Фингерпринтинг Canvas и Защита аудио-отпечатка.

#Webgl#fingerprinting#Gpu#Privacy#Webgl2

Переведите BotBrowser из исследований в продакшн

Используйте эти руководства, чтобы понять модель, а затем перейти к кроссплатформенной валидации, изолированным контекстам и масштабируемому браузерному развертыванию.