Назад в Центр знаний
Отпечатки

Сигналы Android WebView в CreepJS: границы вывода

Разберите сигналы Android WebView по HTTP, JavaScript, worker и мостам приложения; узнайте, что проверяет исходный код CreepJS и чего он не доказывает.

BotBrowser Team

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

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

Эта статья относится к редакционной библиотеке. Для пошаговой настройки, справки и постоянных обновлений переходите сразу в соответствующий раздел docs.

BotBrowser поддерживает заявленную идентичность Android WebView для разрешённых проверок совместимости, но не может определить, как частный anti-bot сервис классифицирует встроенный браузер. Конфигурация WebView использует явно заданный шаблон --user-agent с wv, а не выбирает значение X-Requested-With конкретного приложения. Практический вопрос уже: какой слой выдал каждое значение и какие сравнения страница действительно может выполнить?

TL;DR

  • ; wv в User-Agent указывает на семейство WebView, а не на конкретное приложение.
  • X-Requested-With и window.android зависят от host-приложения; ни один из них не универсален.
  • Navigator-модуль CreepJS сравнивает выбранные значения страницы со значениями worker и читает User-Agent Client Hints.
  • Несовпадение означает, что две записи различаются. Оно не устанавливает причину и не доказывает автоматизацию.

Содержание

Слои сигналов: HTTP-заголовки, JavaScript страницы, значения worker и необязательные мосты приложения
Происхождение сигнала отделяет наблюдения браузера от идентичности приложения и вывода об автоматизации.

Смотреть видео

В этом видео на английском языке сигналы Android WebView разделены на заголовки запроса, JavaScript страницы, значения worker и необязательные мосты приложения. Оно показывает, что может и чего не может установить контролируемый запуск браузера. Видео не подтверждает подлинность host-приложения и не воспроизводит реальное устройство Android WebView.

Host-приложение не равно поверхности браузера

Android WebView является компонентом браузера, встроенным в Android-приложение. Страница может наблюдать свойства браузера и запросов, а приложение-хост может выбрать User-Agent, добавить заголовки или открыть JavaScript-мост. Это разные решения с разной областью действия, их следует записывать отдельно.

Документация BotBrowser об Android WebView описывает, как настройки заявленной идентичности представляют форму User-Agent с wv и необязательные заголовки приложения. Вопрос детектирования точнее: что детектор может вывести из каждого слоя и что остаётся неизвестным? Для настройки идентичности используйте руководство по Android WebView; о том, как CreepJS группирует независимые наблюдения, читайте в разборе групп сигналов и пределов наблюдения CreepJS.

Источник каждого сигнала

СигналНаблюдаемый слойЧто он может подтвердитьЧего он не доказывает сам по себе
User-Agent с ; wvHTTP-запрос и navigator.userAgentПредставлен UA в стиле WebViewКакое приложение встроило браузер и актуально ли значение
Sec-CH-UA и navigator.userAgentDataЗаголовки запроса и JavaScript, если доступныБренд и платформу данного контекстаЧто все Android WebView показывают одинаковые hints
navigator.platformJavaScript страницыНаблюдение о семействе платформыМодель устройства или host-приложение
Значения WorkerNavigatorJavaScript workerСовпадают ли выбранные значения страницы и workerСоответствует ли одно из них физическому устройству
X-Requested-WithHTTP-запрос, если приложение отправляет егоПриложение могло добавить заголовок, похожий на идентификатор пакетаУниверсальный маркер WebView или доверенную идентичность приложения
window.android или другой мостJavaScript, только если мост внедрёнHost открыл интерфейс с заданным именемЧто все приложения его открывают или что методы безопасно вызывать

Android предоставляет User-Agent через WebSettings, а host может его настроить. Android также описывает addJavascriptInterface как явный вызов приложения; имя моста выбирает сама app. Поэтому отсутствие моста не исключает WebView, а его имя нельзя считать аутентифицированным идентификатором пакета.

Заголовки и JavaScript следует хранить в разных строках записи. Сервер получает заголовок до запуска кода страницы, а код видит свойства собственного контекста. Редирект, сервис-воркер, оболочка приложения или смена версии могут повлиять на один слой, не меняя остальные.

Семейства платформы слишком широки для WebView

Помощник CreepJS getReportedPlatform() сводит несколько названий систем к широким семействам. В разборе User-Agent строки android, linux и cros относятся к одной категории Linux. Разбор navigator.platform также объединяет android, arm и linux в это семейство. Такая группировка подходит для проверки согласованности, но теряет различия: совпадение семейства Android не распознаёт WebView и не называет host-приложение.

Navigator-модуль отдельно ищет узнаваемые подстроки и принимает android среди допустимых меток. Это проверка известности строки для данной ревизии, а не проверка того, какое приложение её создало. Храните исходное поле, нормализованное семейство и результат проверки в разных колонках. Запись только Android = true уже не показывает, пришло ли значение из UA, navigator.platform или HTTP-заголовка.

Это различие полезно при сравнении WebView, встроенной вкладки Chrome и полного Chrome. Все три могут работать на Android, но сообщать разные сочетания идентичности браузера и поведения host-приложения. Совпадение широкой категории не доказывает равенство брендов, заголовков или JavaScript-мостов.

У проверок navigator разные условия срабатывания

Закреплённый модуль не объединяет все необычные значения в один результат. Если существует глобальный объект chrome, код проверяет, содержит ли navigator.userAgent значение navigator.appVersion. Он также ищет пробелы в начале и конце строки или повторные пробелы и применяет собственную проверку gibberish. Это наблюдения о качестве User-Agent. Затем userAgent сравнивается со значением worker, и разница контекстов помечается отдельно.

Для deviceMemory исходник распознаёт 0.25, 0.5, 1, 2, 4, 8, 16 и 32. Если доступен performance.memory.jsHeapSizeLimit, код переводит лимит в гигабайты и проверяет, превышает ли он заявленную память. Значение также сравнивается с worker. У hardwareConcurrency есть отдельная проверка равенства страницы и worker. Это разные условия, а не единый Android-оценочный балл.

Путь языка сравнивает первые два символа navigator.language и первой записи navigator.languages. Если оба поля страницы имеют истинное значение, код после сравнения возвращает форматированный результат независимо от совпадения префиксов. Сравнения языка с worker выполняются только вне этой ветки. Проверка plugins устроена иначе: navigator.plugins рассматривается вместе с navigator.mimeTypes. Отчёт о совместимости должен называть конкретное свойство и условие проверки, а не сводить несвязанные условия к ярлыку WebView.

Client Hints доступен не всегда

Navigator-модуль CreepJS не возвращает результат User-Agent Client Hints, если нет navigator.userAgentData или getHighEntropyValues(). При наличии обоих API запрашиваются platform, platformVersion, architecture, bitness, model и uaFullVersion, после чего они объединяются с низкоэнтропийными brands и mobile.

Перед выводом код исключает бренды, в названии которых есть Not, и убирает Chromium из отображаемого списка, если брендов несколько. Это преобразование формата вывода библиотеки. Оно не доказывает отсутствие Chromium в браузере и не означает, что все платформы возвращают одинаковые высокоэнтропийные поля.

Различайте три состояния: API отсутствует, запрошенное значение пропущено или API вернул значение. Указанные источники подтверждают условность Client Hints, но не устанавливают причину пропуска значения. Перед сравнением отметьте наблюдаемое состояние, чтобы не принять отсутствующую подсказку за противоречивое значение.

Что проверяет закреплённый исходный код CreepJS

Публичная ревизия CreepJS зафиксирована на commit 10aa6724cd33a1015db1574211890518cd04f0cc. Её navigator-модуль принимает Android среди нескольких распознаваемых подстрок navigator.platform. Он также сопоставляет семейство ОС, полученное из User-Agent, с заявленной платформой. Это проверка согласованности, а не специальное правило распознавания WebView.

Этот же модуль сравнивает выбранные значения navigator страницы с данными из worker. В коде перечислены platform, userAgent, deviceMemory, hardwareConcurrency, language и languages; сравнения языка с worker находятся вне ветки, где оба языковых поля страницы имеют истинное значение. Если API доступен, путь User-Agent Client Hints запрашивает, среди прочего, platform, platformVersion, architecture, bitness, model и uaFullVersion. Это конкретные детали закреплённого navigator-модуля, а не утверждение, что каждое Android WebView предоставляет все поля.

Отдельный headless-модуль выводит группы условий, видимых браузеру. Его группы и входные данные нельзя сводить к выводу об Android WebView. В разборе headless-проверок CreepJS объясняется, почему эти группы отвечают на разные вопросы.

Исходники позволяют сделать ограниченный вывод: изученные модули CreepJS сравнивают отдельные поверхности и сообщают о выбранных headless-условиях. Эти проверки не подтверждают пакет Android, создавший WebView, и не раскрывают правила частного стороннего классификатора.

Отделяйте признаки WebView от выводов о другом

В отчёте совместимости используйте четыре метки вместо одного бинарного вердикта:

Метка отчётаМинимальные данныеДопустимая интерпретация
Контекст семейства AndroidСогласованные наблюдения платформы Android и UAВидимый контекст сообщает семейство Android
Контекст в стиле WebViewUA или бренд WebView с раздельной записью запроса и страницыКонтекст показывает один или несколько признаков WebView
Различие контекстовРазличается указанное сравнение page/worker или header/JavaScriptЭти наблюдения не совпали в данном запуске
Вывод об автоматизацииНезависимые данные и документированное правило решенияОдного сигнала страницы недостаточно

Это различие важно при проверке согласованности бренда браузера. Бренд, платформа и поведение встроенного приложения связаны, но это не взаимозаменяемые поля. Изменение navigator.platform не объясняет другой HTTP-заголовок, если одна запись не связывает оба наблюдения и не сохраняет их происхождение.

Несовпадение показывает только различие

В этом исходнике несовпадение page/worker доказывает только, что сравниваемые значения отличаются в наблюдаемых контекстах. Оно не устанавливает, какое значение ожидается для конкретной версии, и не объясняет причину. Код описывает собственное сравнение, но не аутентифицирует приложение, систему, WebView-провайдера или правила стороннего сервиса.

Разделяйте четыре утверждения: наблюдаемое значение и его слой; присутствует ли поле и доступно ли чтению; какая именно пара различается, например navigator.platform и platform worker; и какой узкий вывод допустим для теста совместимости собственного приложения. Более широкий вывод об автоматизации требует независимого и документированного правила принятия решения.

Не переносите найденное различие одного поля на всю сессию. Изменённый X-Requested-With сам по себе ничего не говорит о navigator.userAgentData; несовпадение worker не описывает мост приложения. Такое разделение сохраняет диагностическую ценность без заявления об идентичности, которого измерение не подтверждает.

Результаты шрифтов образуют отдельную поверхность: анализ таблиц шрифтов CreepJS показывает, почему обнаруженная группа шрифтов не идентифицирует приложение, разместившее WebView.

Последствие для приватности конкретно: window.android может открывать методы приложения, а Android предупреждает, что JavaScript-мосты расширяют границу безопасности. При проверке записывайте наличие моста, не вызывая посторонние методы и не собирая ненужные данные приложения.

Контролируемое сравнение собственных приложений

Для приложения, которым вы владеете, сравните три контекста на одной версии Android и сборке приложения: WebView этого приложения, встроенную вкладку Chrome, если продукт её использует, и полный Chrome. Оставьте одинаковыми origin страницы и проверочное действие. Приведённая таблица описывает план сбора, а не отчёт о запуске:

Точка сбораЗаписыватьХранить отдельно
ЗапросUser-Agent, заголовки Client Hints и X-Requested-With, если естьПервую навигацию и последующие запросы
Страницаnavigator.userAgent, navigator.platform, доступные поля userAgentDataОтсутствие, отказ и пустая строка являются разными состояниями
WorkerСоответствующие поля WorkerNavigatorМомент создания worker и его origin
Host-приложениеНамеренно ли зарегистрирован мост и каково его документированное имяНе вызывайте методы только для распознавания контейнера

Фиксируйте версии Android, WebView-провайдера, приложения и страницы вместе. Разные версии провайдера могут превратить легитимное обновление в кажущуюся несогласованность. Для каждой отличающейся ячейки укажите слой и состояние поля: отсутствует, недоступно или имеет другое значение. Не превращайте эти состояния в единую оценку.

Сохраняйте контекст и ограничивайте сбор

Используйте одно действие на собственной странице, тот же origin и сопоставимый момент навигации. Записывайте версии Android, WebView, приложения и браузера, язык, состояние разрешений и тип контекста: WebView, встроенная вкладка Chrome или полный Chrome. Эти поля объясняют сравнение, но не являются вердиктом. При обновлении сохраняйте обе версии, а не называйте новое значение ложью.

Заголовок X-Requested-With может содержать название пакета приложения, поэтому храните его только при необходимости для разрешённой проверки. Для общего отчёта часто достаточно признака наличия или замаскированного значения. JavaScript-мост может открывать методы приложения; фиксируйте, что он намеренно зарегистрирован, и его документированное имя, но не вызывайте посторонние методы и не сохраняйте данные приложения. Предупреждение Android о addJavascriptInterface описывает также границу безопасности.

Связывайте каждое сравнение с источником: запрос для заголовков, страница для navigator, worker для его значений. Краткая запись может содержать имя поля, состояние, версии и сравниваемую пару без пользовательского содержимого. Этого достаточно для проверки совместимости собственного приложения и это снижает случайный сбор идентификаторов пакетов и данных приложения.

Сравнивайте одинаковые моменты запроса

Записывайте основную навигацию отдельно от последующих запросов ресурсов. Приложение может добавлять заголовок лишь к части запросов; поэтому заголовок одного изображения нельзя сравнивать с JavaScript итогового документа так, будто это единое наблюдение. Связывайте запрос с навигацией, origin, сборкой приложения, версией браузера и состоянием разрешений. Если есть редиректы, фиксируйте каждый переход, а не объединяйте первый и конечный адреса в одну транзакцию. Сравнение описывает данный контекст и момент, а не все устройства с той же основной версией Android.

Вопросы

Доказывает ли ; wv, что запрос пришёл из Android WebView?

Нет. Это узнаваемая строка User-Agent, которую приложение может настроить. Она описывает представленное значение, но не доказывает приложение-хост или источник запроса.

Определяет ли CreepJS Android-приложение, где открыта страница?

Указанные проверки navigator сравнивают видимые значения со значениями worker. Они не аутентифицируют host-пакет. Мост или заголовок, добавленный приложением, зависит от конкретной app и не является универсальным сигналом идентичности CreepJS.

Означает ли расхождение page/worker, что браузер автоматизирован?

Нет. Оно означает, что записанные значения различаются. Причиной также могут быть обновление браузера, доступность API, момент создания контекста или конфигурация приложения. Сначала сохраните точные поля и окружение.

Источники

Практический вывод

Рассматривайте идентификацию WebView как вопрос происхождения сигнала, а не как проверку одного токена. Записывайте заголовки, свойства страницы, сравнения worker и необязательные мосты отдельно. В QA собственных приложений сравнивайте одинаковые контексты и сохраняйте отсутствующие значения: расхождение полезно для совместимости, но не доказывает устройство или решение стороннего анти-бота.

#CreepJS#Android WebView#сигналы браузера

Эта статья входит в руководство: Что такое отпечаток браузера?

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

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