Демо
Фавикон сайта — маленький значок .ico размером 16*16 или 32*32 пикселей на вкладке браузера. Помогает ориентироваться в сотнях вкладок. У твиттера синяя птичка, у Gmail красный символ почты, у Википедии жирное W.
Но оказывается, что эти значки представляют собой уязвимость, через которую можно выполнять фингерпринтинг — идентифицировать юзера даже через VPN и режим инкогнито в браузере (см. демо).
Немецкий программист Йонас Штреле (Jonas Strehle) в репозитории на Github описывает метод установки неудаляемого суперкуки через фавиконы: «Суперкуки через фавиконы присваивают посетителям сайта уникальные ID. В отличие от традиционных методов отслеживания, этот ID сохраняется практически навсегда и не может быть удалён пользователем с помощью простых методов. Метод отслеживания работает даже в режиме инкогнито. Суперкуки не удаляются при очистке кэша, закрытии браузера или перезапуске системы, использовании VPN или блокировщиков рекламы».
Как работает фингерпринтинг
Чтобы отобразить иконку, в код страницы вставляется такой атрибут:
<link rel="icon" href="/favicon.ico" type="image/x-icon">
Фавиконы должны быть очень легко доступны через браузер. Поэтому они кэшируются в отдельной локальной базе данных, так называемом кэше фавиконов (F-Cache), где хранится URL, идентификатор фавикона и время жизни.
Когда пользователь заходит на сайт, браузер проверяет локальный F-Cache на наличие записи, содержащей URL-адрес активного веб-сайта. Если запись найдена, значок загружается из кэша. Если запись отсутствует, браузер отправляет GET-запрос, чтобы загрузить фавикон с сервера.
Такой механизм позволяет серверу довольно много узнать о посетителе. Комбинируя статусы доставленных и не доставленных фавиконов для определённых URL, клиенту присваивается уникальный шаблон (идентификационный номер). Затем ID сохраняется:
const N = 4;
const ROUTES = ["/a", "/b", "/c", "/d"];
const ID = generateNewID(); // -> 1010 • (select unassigned decimal number, here ten: 10 -> 1010b in binary)
const vector = generateVectorFromID(ID); // -> ["/a", "/c"] • (because [a, b, c, d] where [1, 0, 1, 0] is 1 -> a, c)
После повторной загрузки сайта этот ID можно восстановить по списку сетевых запросов, отправленных клиентом для недостающих фавиконов — и таким образом идентифицировать браузер.
const visitedRoutes = [];
Webserver.onvisit = (route) => visitedRoutes.push(route); // -> ["/b", "/d"]
Webserver.ondone = () => { const ID = getIDFromVector(visitedRoutes) }; // -> 10 • (because "/a" and "/b" are missing -> 1010b)
Автор запустил сайт для демонстрации фингерпринтинга с помощью фавиконов. Опубликован исходный код и детальное описание механизма.
В этой уязвимости самое неприятное — это то, насколько легко можно обойти традиционные методы, которые люди используют для защиты своей приватности. По словам Штреле, фингерпринтинг пробивает «приватный» режим Chrome, Safari, Edge и Firefox. Очистка кэша, VPN или блокировщик рекламы — ничто не помешает вредоносным фавиконам.
К таким же выводам пришли исследователи из университета Иллинойса в опубликованной недавно научной работе "Tales of Favicons and Caches: Persistent Tracking in Modern Browsers": «Мы обнаружили, что сочетание нашей техники отслеживания на фавиконах с фингерпринтингом через неизменяемые атрибуты браузера позволяет сайту восстановить 32-битный идентификатор трекинга за две секунды», — говорится в исследовании. — В связи с серьёзностью уязвимости мы предлагаем внести изменения в кэширование фавиконов браузерами, чтобы предотвратить эту форму трекинга. Мы передали наши результаты разработчикам поставщикам браузеров, которые в настоящее время изучают варианты смягчения последствий».
На данный момент фингерпринтинг через фавиконы работает во всех крупнейших браузерах, в том числе в мобильных (значок плюса):
Браузер |
Windows |
MacOS |
Linux |
iOS |
Android |
Примечания |
---|---|---|---|---|---|---|
Chrome (v 87.0) | + | + | + | + | + | ? |
Safari (v 14.0) | ? | + | ? | + | ? | ? |
Edge (v 87.0) | + | + | ? | ? | + | ? |
Firefox (v 85.0) | + | + | ? | ? | ? | Другой фингерпринтинг в режиме инкогнито |
Brave (v 1.19.92) | + | + | + | ? | ? | ? |
В следующей таблице указано минимальное время, необходимое для проведения атаки. Реальный показатель зависит также от дополнительных факторов, таких как скорость интернет-соединения, местонахождение, производительность железа и тип браузера.
Редиректов (N бит) |
Кол-во различимых клиентов | Время записи | Время чтения | Масштаб атаки |
---|---|---|---|---|
2 | 4 | < 300 мс | < 300 мс | Один юзер с четырьмя браузерами |
3 | 8 | < 300 мс | ~ 300 мс | Примерная численность Кардашьянов |
4 | 16 | < 1 с | ~ 1 с | Кучка ваших соседей |
8 | 256 | < 1 с | ~ 1 с | Все ваши френды на Facebook |
10 | 1024 | < 1,2 с | ~ 1 с | Очень маленькая деревня |
20 | 1 048 576 | < 1,8 с | < 1,5 с | Небольшой город (Сан-Хосе) |
24 | 16 777 216 | < 2,4 с | < 2 с | Все Нидерланды |
32 | 4 294 967 296 | ~ 3 с | < 3 с | Все люди с доступом в интернет |
34 | 17 179 869 184 | ~ 4 с | ~ 4 с | Все люди с доступом в интернет и 4 браузерами у каждого |