Ваш список шрифтов собирался годами. Пару сотен положила туда операционная система, Office добавил свои, Adobe докладывала новые с каждым приложением, а декоративный шрифт, установленный ради одного проекта в 2021-м, так никуда и не делся. Любой сайт может прочитать итог за несколько сотен миллисекунд, без всякого запроса разрешения, — и чем длиннее становился этот список, тем меньше шансов, что у кого-то ещё он совпадает с вашим.
Браузеры никогда не давали сайтам возможности просто запросить список шрифтов — именно потому, что он так хорошо идентифицирует. Как выяснилось, это ничему не помешало. Скрипт может не спрашивать, а измерять: ему хватает невидимой строки текста и двух замеров ширины. Виджет на этой странице прогоняет это измерение по 175 шрифтам-кандидатам и показывает, что выдаёт ваш браузер, а заодно — насколько ваш набор распространён среди всех, кто запускал сканирование.
Как работает фингерпринтинг шрифтов: трюк с измерением
Вот вся техника целиком. Скрипт создаёт невидимый <span> с бессмысленной строкой mmmmmmmmmmlli кеглем 72 пикселя и спрашивает у браузера, какой ширины она получилась в generic-семействе вроде monospace. Затем меняет семейство на "Segoe UI", monospace и читает ширину снова. Если Segoe UI установлен, браузер отрисует его — и ширина сдвинется. Если нет, сработает запасной вариант, и число останется на месте. Один шрифт-кандидат, два замера ширины, ни одного API.
И строка выбрана не случайно: m и l — самая широкая и самая узкая строчные буквы в большинстве гарнитур, поэтому замена одного шрифта на другой сдвигает суммарную ширину настолько далеко, насколько это вообще возможно. Посмотрите, как это происходит на вашей собственной машине:
font-family: monospace …font-family: "Segoe UI", monospace …Есть способы и поаккуратнее. document.fonts.check() выдаёт тот же ответ булевым значением за один вызов — в браузерах на Chromium, благодаря причуде, нарушающей спецификацию; Firefox и Safari отвечают true про любой шрифт, какой ни назови, — а измерение текста на canvas и вовсе не трогает DOM. Ровно один вежливый API в этой области у веб-платформы всё же есть: queryLocalFonts() возвращает настоящие имена шрифтов и даже сами файлы шрифтов — после того как пользователь одобрит запрос разрешения. Ни один трекер этот запрос вам ещё ни разу не показывал.
Всё это семейство техник называется перечислением шрифтов (font enumeration), и трекеры — не единственные его клиенты. Антифрод-системы и детекторы ботов гоняют тот же зонд, чтобы проверить, что устройство — то, за что себя выдаёт, поэтому результат следует за вами туда, куда простому рекламщику хода нет: в платёжные процессы, риск-скоринг входа, проверки аккаунтов.
Что выдаёт список установленных шрифтов
Ценен этот список не длиной, а тем, в чём признаётся каждая строчка. Шрифты появляются на машине как побочный эффект всего остального, что вы ставите. Segoe UI означает Windows. Helvetica Neue означает Apple. DejaVu Sans означает Linux. Bahnschrift сужает Windows до версии 10 и новее, а Segoe UI Variable говорит об 11. Minion Pro или Myriad Pro значит, что на этой машине бывал софт Adobe. Windows, установленная под китайский язык, несёт шрифты, которым в американской взяться неоткуда. Ваши шрифты — это летопись того, чем вы пользуетесь и примерно когда вы это поставили:
Segoe UI поставляется с WindowsHelvetica Neue поставляется с macOS и iOSDejaVu Sans поставляется с десктопным LinuxBahnschrift появился в Windows 10, раньше отсутствовалSegoe UI Variable появился в Windows 11Minion Pro устанавливается приложениями AdobeMyriad Pro устанавливается приложениями AdobeЭто тот же класс утечек, что мы разбирали в статье «Один браузер, пять версий ОС»: ярлыки, которые сообщает браузер, можно переписать, но машина за ними остаётся собой. Поддельный User-Agent под macOS поверх списка шрифтов, полного Segoe и Calibri, — противоречие, которое любой скрипт замечает за миллисекунды.
В исследовании Panopticlick от EFF список шрифтов — тогда его собирали через Flash и Java — нёс 13,9 бита идентифицирующей информации: больше, чем любой другой измеренный сигнал браузерного фингерпринтинга, кроме списка плагинов. Плагины браузеры с тех пор обезвредили — navigator.plugins везде сообщает один и тот же короткий список PDF-просмотрщиков (или вовсе ничего), — а шрифты остаются ровно настолько же измеримыми, как в 2010-м. К тому же список утекает дважды: один раз как список, второй — через canvas-фингерпринтинг, где доступные рендереру шрифты участвуют в решении, какие именно пиксели даст отрисовка на canvas.
И список этот терпелив. Он не меняется от очистки cookie, не меняется в окне инкогнито, а до вашего VPN ему нет ровно никакого дела. Меняется он, когда вы ставите или удаляете программы, — у большинства людей это случается несколько раз в год. По меркам трекинговых идентификаторов это долгий срок годности.
Можно ли защититься от фингерпринтинга шрифтов? Ловушка блокировки
Существуют расширения, обещающие остановить измерение — блокировкой зондов или подмешиванием шума. Проблема та же, на которой по всему этому сайту горят половинчатые подмены: защита встречается реже, чем то, что она прячет.
Десктопный Chrome на Windows, сообщающий лишь горстку веб-безопасных шрифтов, не анонимен — он странен, а странность и есть то, чем кормится фингерпринтинг. Рандомизаторы ещё хуже. Настоящий список шрифтов стабилен месяцами, поэтому список, мутирующий от визита к визиту, помечает вас как одного из немногих владельцев именно этого расширения. А расширения, подделывающие сами числа, делают это, переопределяя те самые функции, которыми страница измеряет. Отсюда вторая проблема: переопределённая встроенная функция при инспекции перестаёт сообщать [native code] — та же примета, что выдаёт stealth-плагины.
Браузеры, защищающиеся от этого всерьёз, делают это целиком. Tor Browser поставляется с собственным набором шрифтов и ограничивает сайты этим фиксированным списком, так что каждый пользователь Tor предъявляет примерно один и тот же короткий набор. Это работает — и заодно сообщает каждому сайту, что у вас Tor. Brave вместо этого прибегает к фарблингу: для каждого сайта и каждой сессии он показывает трекерам шрифты вашей ОС плюс случайную выборку из установленных, так что список, собранный трекером сегодня, тихо расходится с завтрашним, ни разу не выглядя невозможным. Оба подхода работают потому, что вокруг них построен весь браузер, — в отличие от заплатки, воюющей с браузером, внутри которого она сидит.
Что делать на практике
- Сначала посмотрите на собственный список. Виджет на этой странице уже измерил ваш браузер. Разверните список шрифтов, чтобы увидеть ровно то, что видит любой сайт, и проверьте, насколько распространён именно ваш набор среди всех сканирований на этом сайте. О наборе, существующем в единственном экземпляре, лучше узнать до того, как это начнёт иметь значение.
- Не латайте по кусочкам. Расширение, блокирующее шрифты, поверх во всём остальном обычного браузера делает вас более редким, а не более защищённым. Если хотите такую защиту в повседневном сёрфинге, возьмите браузер, спроектированный вокруг неё, — Brave или Tor — и принимайте их компромиссы осознанно.
- Если вы ведёте несколько личностей, список шрифтов — часть личности. Каждому профилю нужны шрифты, согласующиеся с ОС, которую он заявляет, — сессия за сессией. Incogniton даёт каждому профилю собственный список шрифтов и держит его стабильным от сессии к сессии, так что биография, которую читает сайт, принадлежит профилю, а не вашей машине.
Ваши шрифты отвечают на вопросы о вас с тех пор, как у вас появилась эта машина. Виджет выше показывает, что именно они рассказывали, а полное сканирование браузера — что к этому добавляет весь остальной браузер.