Группы сигналов CreepJS и как он их объединяет
Один зонд по CreepJS: девять независимых шаблонов образуют упорядоченную строку решения, и один из них ловится только сравнением двух групп.
BotBrowser Team
Нужна структурированная документация по теме Отпечатки?
Эта статья относится к редакционной библиотеке. Для пошаговой настройки, справки и постоянных обновлений переходите сразу в соответствующий раздел docs.
BotBrowser позволяет воспроизвести авторизованный фикстур того же источника под объявленным профилем и сохранить ограниченную запись того, что сообщила каждая группа зондов, но он не может заставить одну группу совпасть с другой, описывающей иную поверхность, не может скрыть группу, которую заблокировали вместо того чтобы ответить, и не может изменить порядок, в котором строка решения называет свои причины. CreepJS читается здесь по открытому исходному коду, его решение из девяти шаблонов воспроизводится, и фиксируется, какие шаблоны ставит одна группа, какому нужно расхождение двух групп, почему порядок девяти определяет сообщённую причину и что могут дать два серверных шаблона изнутри страницы.
Кратко
- CreepJS запускает больше двадцати групп зондов и сворачивает их в строку решения из девяти бит в фиксированном порядке, вместе с отдельным дайджестом каждой группы.
- Чистый профиль не ставит ни одного бита: зонд печатает
clean -> botHash=000000000 set=0 badBot=none. - Четыре шаблона ставит одна группа: область Worker, которая соврала, несовпадение версии возможностей, заменённый
Function.prototype.toStringи заблокированная область Worker. - Заблокированная область это самый дешёвый одиночный сигнал, потому что он срабатывает даже когда никто не соврал:
worker-blocked -> botHash=000000100. - Одному шаблону нужны две группы: платформа шрифтов, расходящаяся с системой, которую заявляет user agent Worker.
- Такое межгрупповое расхождение не имеет своего бита, оно питает шаблон крайней лжи, поэтому
font-vs-ua-feeds-extreme -> botHash=000010000 badBot=extremeLieCount. - Порядок девяти определяет сообщённую причину: при четырёх битах зонд печатает
botHash=110100100 badBot=liedWorkerScope, и обратный порядок входа ничего не меняет. - Два шаблона вычисляются на сервере, поэтому изнутри страницы они всегда нули:
server-bits -> positions=6,8 always=00.
Содержание
- Что такое девять бит и откуда они
- Какие группы ставят бит сами
- Какому биту нужно расхождение двух групп
- Почему порядок бит важен
- Запись одного показания перекрёстной сверки
Что такое девять бит и откуда они
CreepJS не выдаёт одну оценку. Он запускает набор независимых групп зондов, сжимает вывод каждой группы в отдельный дайджест, а затем сворачивает девять конкретных шаблонов в упорядоченную строку решения. Девять берутся из разных групп, и это весь замысел:
clean -> botHash=000000000 set=0 badBot=none
Девять нулей для браузера, который ничего не поднял. Каждая позиция называет шаблон, взятый из другой части страницы: собственный отчёт области Worker, версия платформы, выведенная из измерения шрифтов, ведёт ли себя Function.prototype.toString всё ещё как нативный, совпал ли список возможностей с объявленной версией, крайнее число отдельных несоответствий, избыток рыхлых отпечатков, была ли область Worker заблокирована, оценка смешивания с толпой и серверный шаблон.
Несовпадение платформы между двумя группами это случай, который почему один странный сигнал не выносит вердикт оценивает иначе, чем одну тонкую поверхность. Дайджесты по группам и строка решения отвечают на разные вопросы. Дайджест говорит «эти два прогона группы canvas дали те же байты», что является утверждением о стабильности одной поверхности. Строка говорит «эти девять названных условий были истинны», что является утверждением о странице целиком. У профиля может быть совершенно стабильный дайджест canvas и всё равно поставленный бит, потому что бит приходит из другой группы.
Это разделение стоит держать в голове при чтении любого отчёта об отпечатках. Стабильный дайджест группы часто принимают за хороший результат, и это не то же утверждение. Стабильность означает, что группа воспроизводима; она ничего не говорит о том, согласуется ли вывод этой группы с выводом другой.
Какие группы ставят бит сами
Четыре из девяти шаблонов ставит одна группа без всякого сравнения. Зонд прогоняет каждый против чистой базы:
worker-scope-lied -> botHash=100000000 set=1 badBot=liedWorkerScope
features-version-lied -> botHash=000100000 set=1 badBot=outsideFeaturesVersion
proxy-toString -> botHash=001000000 set=1 badBot=functionToStringHasProxy
worker-blocked -> botHash=000000100 set=1 badBot=workerScopeIsBlocked
Каждая строка ставит ровно один бит, и каждый бит в своей позиции, поэтому сама строка записывает, какая группа сказала. Область Worker, сообщившая что-то несогласованное, ставит первую позицию. Список возможностей, не совпавший с объявленной версией, ставит четвёртую. Function.prototype.toString, который больше не ведёт себя как нативный, ставит третью. Область Worker, которую не удалось создать, ставит седьмую.
Worker, сообщающий иное значение, чем главная страница, это один из немногих сигналов, которых не даёт ни один законный клиент, и целостность API между realm фиксирует это подробно. Случай заблокированной области заслуживает паузы, потому что он срабатывает без всякой лжи. Никто не сообщил неверного значения; страница просто не получила область Worker, которая ответит. Это делает его самым дешёвым одиночным сигналом во всём наборе: страница может быть совершенно согласованной на каждой поверхности, которую она раскрывает, и всё равно поставить этот бит, не раскрыв одну. Любой тест, который читает только ответившие поверхности, его пропустит.
Позиция Function.prototype.toString это та, на которую страница может влиять напрямую, и разбор подменённые нативные функции и что видит список toString описывает, какие правки переживают эту проверку и какие обёртки её проходят. Строка здесь только фиксирует, что шаблон сработал; она не говорит, какая правка его вызвала.
Какому биту нужно расхождение двух групп
Один шаблон нельзя оценить из одной группы, потому что он существует именно чтобы сравнить две. Зонд даёт ему user agent и платформу шрифтов и фиксирует, что решает сравнение:
cross:agree-win -> uaOS=WINDOWS fontOS=WINDOWS fontOSBad=false
cross:agree-mac -> uaOS=APPLE fontOS=APPLE fontOSBad=false
cross:disagree-ua-mac-font-win -> uaOS=APPLE fontOS=WINDOWS fontOSBad=true
cross:disagree-ua-win-font-mac -> uaOS=WINDOWS fontOS=APPLE fontOSBad=true
cross:android-with-mac-font -> uaOS=LINUX fontOS=APPLE fontOSBad=true
Когда обе группы называют одно семейство платформы, ничего не срабатывает. Когда они называют разные семейства, сравнение срабатывает в любом направлении, и оно также срабатывает для user agent Android с платформой шрифтов, которая читается как Apple. Направление не важно, только расхождение, и именно это делает проверку согласованности проверкой, а не порогом по одному значению.
Случай Android самый показательный для развёртывания. Профиль, сообщающий user agent Android, тогда как его измерения шрифтов разрешаются как настольное семейство Apple, ставит этот шаблон, хотя ни одна из групп по отдельности не выглядит неверной. User agent это правдоподобная строка Android, а платформа шрифтов правдоподобная строка Apple; они просто не могут быть верны для одного устройства.
Что шаблон делает с этим расхождением, это самая легко пропускаемая часть:
font-vs-ua-feeds-extreme -> botHash=000010000 set=1 badBot=extremeLieCount
Межгрупповое расхождение не имеет своего бита. Оно питает пятую позицию, шаблон крайней лжи, наравне с абсолютным числом отдельных несоответствий. Поэтому отчёт, говорящий, что бит крайней лжи поставлен, может означать, что страница накопила очень много мелких несогласованностей, а может означать, что хватило одного межгруппового расхождения. Бит не различает эти два случая, и читающему нужно вернуться к выводу по группам, чтобы понять какой.
Это решение намеренно, и у него есть цена. Складывание качественного расхождения в тот же бит, что и количественный счёт, означает, что строка теряет информацию, которая у групп ещё есть. Строка это сводка, и сводка теряет данные конкретным, задокументированным образом.
Почему порядок бит важен
Девять позиций не равны, потому что решение сообщает первый поставленный бит как свою причину. Зонд ставит четыре шаблона сразу, затем повторяет те же четыре в другом порядке входа:
many-bits -> botHash=110100100 set=4 badBot=liedWorkerScope
many-bits-reversed-input -> botHash=110100100 set=4 badBot=liedWorkerScope
Четыре бита поставлены, и сообщённая причина всегда самая левая. Порядок входа не меняет ни строку, ни причину, значит порядок живёт в фиксированном списке, а не в порядке завершения групп. Страница, поставившая четыре шаблона, узнаёт только об одном, и это тот, что левее всех.
Практическое следствие: одна сообщённая причина не означает одну находку. Отчёт, называющий одну причину рядом с четырьмя поставленными битами, говорит, что их четыре, и выбирает показать самую левую. Кто читает только причину, недооценит то, что страница действительно сделала.
Две из девяти позиций нельзя поставить изнутри страницы:
server-bits -> positions=6,8 always=00
Позиции избытка рыхлых отпечатков и смешивания с толпой вычисляются там, где можно сравнить много сессий, поэтому браузер, оценивающий сам себя, сообщает ноль для обеих независимо от того, что делает страница. Проверка на стороне страницы поэтому покрывает семь из девяти шаблонов, а два, которые она не покрывает, требуют популяции, а не сессии.
Строки с одним битом говорят то же о детализации:
single:liedWorkerScope -> 100000000 position=1
single:functionToStringHasProxy -> 001000000 position=3
single:workerScopeIsBlocked -> 000000100 position=7
Три разные находки, три разные строки, каждая ровно с одним битом. Строка точна в том, какой шаблон сработал, и молчит о том, насколько сильно. Страница, поставившая первую позицию потому что область Worker сообщила одно неверное значение, и страница, поставившая её потому что область противоречила себе в шести местах, дают одну и ту же строку.
Таблица версий Windows, от которой зависит шаблон версии платформы, показывает, почему он тоже груб:
win-release:0.3.0 -> 8.1
win-release:8.0.0 -> 10 (1903|1909)
win-release:13.0.0 -> 11
win-release:15.0.0 -> 11
Каждая версия платформы начиная с 13 соответствует Windows 11, поэтому шаблон не отличает одну сборку Windows 11 от другой. Это проверка уровня семейства, и именно поэтому она годится для обнаружения несовпадения и бесполезна для определения сборки.
Запись одного показания перекрёстной сверки
Оформленная запись делает четыре поля конкретными. Прогон, вернувший botHash=110100100 с badBot=liedWorkerScope, записывается как строка плюс коммит плюс вывод по группам области Worker, списка возможностей, проверки Function.prototype.toString и измерения шрифтов, и в ней названы две неоценённые позиции. Читатель видит, что сработали четыре шаблона, что сообщённая причина это позиция один, и что сравнение шрифтов против user agent дало вклад через пятую позицию, а не через свой бит.
Показание перекрёстной сверки подтверждает узкое утверждение: эта версия библиотеки, эти группы дали эту строку решения. Четыре поля держат его проверяемым:
- Коммит библиотеки и упорядоченный список шаблонов, потому что позиции и их смысл это код, и перестановка тихо меняет сообщённую причину.
- Вывод по группам рядом со строкой решения, потому что строка складывает качественное расхождение и количественный счёт в один бит, а группы ещё хранят различие.
- Какие шаблоны оценены, а какие нет, потому что два из девяти требуют популяции и всегда нулевые в проверке на стороне страницы.
- Поставленные биты как строку, а не как счёт, потому что четыре бита с одной сообщённой причиной и один бит это разные находки, и счёт их не разделяет.
Публичные источники
- CreepJS
- Модуль решения и дайджестов CreepJS
- Вспомогательные функции классификации платформы CreepJS
- MDN: Worker
- MDN: User-Agent Client Hints
- BotBrowser: справочник согласованности автоматизации
Практический вывод
Читайте результат CreepJS как упорядоченную строку названных шаблонов, а не как оценку, потому что строка говорит, какая группа сказала, а оценка сказала бы только сколько. Воспринимайте заблокированную область Worker как самостоятельную находку, даже когда никто не соврал, поскольку это самый дешёвый одиночный шаблон и самый легко пропускаемый. Ожидайте, что шаблон шрифтов против user agent сработает в любом направлении, и помните, что он питает бит крайней лжи, а не свой собственный, поэтому одна причина не отличает качественное несовпадение от большого числа мелких. О проверке целостности, от которой зависит одна из девяти позиций, читайте подменённые нативные функции и что видит список toString; о том, как оценивается и фильтруется решение из нескольких уровней, читайте почему один странный сигнал не выносит вердикт.
Эта статья входит в руководство: Что такое отпечаток браузера?
Похожие статьи
Как читать сигналы отпечатка браузера
ОтпечаткиПричина отмены, композиция и поздние слушатели
ОтпечаткиЧто такое отпечаток браузера?
ОтпечаткиЛовушки прокси и инварианты среды выполнения
ОтпечаткиСтроки даты: граница между местным временем и UTC
ОтпечаткиDataView: порядок байтов, выравнивание и границы
Переведите BotBrowser из исследований в продакшн
Используйте эти руководства, чтобы понять модель, а затем перейти к кроссплатформенной валидации, изолированным контекстам и масштабируемому браузерному развертыванию.