Антифрод сравнивает не cookie. Он складывает измерения браузера в один слепок и ищет совпадения между аккаунтами. Разбираем, из чего слепок собран, что в нем весит больше всего и почему подмены одного canvas недостаточно.
Сайт видит не «браузер», а сумму измерений. Каждое по отдельности слабое, вместе они дают отпечаток, который переживает чистку cookie и смену IP. Порядок примерно такой:
| Канал | Что измеряется | Насколько различает |
|---|---|---|
| Список шрифтов | какие шрифты установлены в системе | наибольшая энтропия: 9,45 бита, 35% машин уникальны |
| WebGL | строка видеокарты, параметры отрисовки | высокая, привязана к железу |
| Canvas | хэш отрисованной картинки | высокая |
| Аудио | хэш сигнала через Web Audio | высокая на разных машинах |
| Экран и DPR | разрешение и плотность пикселей | средняя |
| Часовой пояс, язык | настройки системы | низкая по отдельности, важна согласованность |
Шрифты стоят первыми не случайно: это поверхность с наибольшей энтропией. 35% машин по одному только списку шрифтов уникальны в потоке.
Первый замер проекта дал неприятный результат. Два профиля на одной машине без набора устройств совпадали по метрикам шрифтов, параметрам WebGL, clientRects и аудио при любой конфигурации. Сайт связывал такие аккаунты независимо от cookie и IP. Этот замер определил всю архитектуру продукта.
Ответ оказался не в том, чтобы «зашумить все», а в том, чтобы дать каждому профилю согласованный набор с настоящего компьютера. После подключения набора устройств те же поверхности стали различаться. Проверено на живых браузерах:
| Поверхность | Различается у двух профилей |
|---|---|
| WebGL вендор и рендерер | да |
| Параметры WebGL | да |
| Геометрия экрана и DPR | да |
| Число ядер и память | да |
| Список шрифтов | да |
| Голоса синтеза речи | да |
| Таблица констант Web Audio | да |
| Canvas | да, шум от сида профиля |
Подмененный canvas при настоящем списке шрифтов ничего не решает: связка происходит по нетронутым каналам. Хуже того, часть каналов трогать нельзя.
Метрики текста общих шрифтов движок намеренно не искажает. У детекторов есть проверка measuretext-grid, которая ловит именно искажение; подделка сделала бы браузер обнаружимым. То же с clientRects (проверка bcr-vs-range). Эти поверхности и не различают: на двух настоящих машинах с одинаковой ОС и DPR ширина Arial совпадет, потому что ее задает файл шрифта и система, а не человек.
Не на слово. Создайте два профиля на бесплатном тарифе, откройте в каждом страницу проверки и сравните сырые значения:
Canvas и WebGL различаются, наборы согласованы. Это видно в сырых значениях, а не в нашем описании. Или откройте тест отпечатка: он снимет ваш браузер и поставит рядом набор профиля.
Один канал пока связывает профили на одной машине. Хэш отрисованного аудио: шум движка привязан к домену, а не к профилю. На двух реальных компьютерах хэши разные, у наших профилей на одной машине они одинаковые. Мы показываем это в панели, в ячейке АУД у каждого профиля, а не в сноске. Практическое правило до собственной сборки движка: профили одной площадки держать на разных машинах.
Аудио-отпечаток: честный остаток · Согласованность важнее количества