Пользователь Bluetooth-наушников с поддержкой multipoint — одновременного подключения к телефону и компьютеру — столкнулся со странным поведением. Обычно приоритет отдаётся звуку с ПК, а телефон подхватывает воспроизведение, когда на компьютере ничего не играет. Схема работала стабильно, пока в Firefox или Chrome не открывалась главная страница AliExpress (другие браузеры не тестировались).
Вскоре после загрузки главной страницы AliExpress звук с телефона обрывался. Закрытие вкладки магазина немедленно всё исправляло. Заглушение вкладки, самого браузера или системного звука в Windows не помогало, при этом на странице не было ни видимого видео, ни музыки, ни какого-либо другого медиаконтента.
Поиск скрытого медиа
Первое предположение — автовоспроизводящееся видео товара или реклама, поэтому проверка началась с типичных подозреваемых:
- элементы <audio> и <video>
- вызовы HTMLMediaElement.play()
- активные метаданные Media Session
- сетевые запросы к медиаресурсам
- встроенные фреймы с медиа
Ни один из вариантов ничего не дал. Ни аудио- или видеоэлементов, ни вызовов воспроизведения, а navigator.mediaSession.playbackState оставался в состоянии none.
Зацепкой стало то, что проблема проявлялась не сразу, а через несколько секунд простоя страницы. После этого страница была проинструментирована ещё до загрузки — вместо поиска обычных медиаэлементов отслеживался Web Audio API.
Идея была простой: обернуть конструктор AudioContext и логировать каждое создание аудио-обрабатывающего контекста:
Дополнительно был обёрнут AudioNode.prototype.connect(), чтобы видеть, подключается ли что-то к audio destination контекста.
Именно это и дало результат — обнаружились два скрытых аудиоконтекста.
При захвате главной страницы AliExpress в состоянии простоя страница создала два объекта AudioContext. Оба перешли в состояние running и оба подключили узлы к AudioContext.destination.
При этом одновременно наблюдалось:
- ноль элементов <audio> или <video>
- ноль вызовов play()
- отсутствие активной Media Session
- отсутствие слышимого звука
Трассировки стека конструктора указывали на два скрипта:
https://assets.aliexpress-media.com/g/AWSC/uab/1.140.0/collina.js
https://assets.aliexpress-media.com/g/AWSC/fireyejs/1.231.67/fireyejs.js
Первый контекст создавался скриптом collina.js, второй — fireyejs.js. Оба лежат в директории AWSC и, по всей видимости, являются частью инструментария Alibaba для защиты браузера и противодействия злоупотреблениям.
Скрипты сильно обфусцированы, но достаточное количество имён и операций сохранилось, чтобы с помощью ИИ разобраться, что делает аудиокод.
Что делает аудиокод
Оба скрипта строят WebAudio-граф примерно такого вида:
Пилообразный осциллятор
-> AnalyserNode
-> ScriptProcessorNode
-> GainNode, выставленный в ноль
-> AudioContext.destination
Осциллятор генерирует известную форму волны. Анализатор измеряет результат после того, как сигнал прошёл через аудиореализацию браузера, и скрипт считывает частотные данные из него.
Гейн выставлен в ноль, поэтому пользователь ничего не должен слышать. Однако граф всё равно подключён к системному аудио destination. Подключение к destination заставляет браузер активно обрабатывать граф, даже несмотря на нулевую итоговую громкость.
Это принципиально отличается от автовоспроизводящегося видео. Здесь нет медиаэлемента, который могло бы остановить обычное управление заглушением вкладки в браузере. С точки зрения страницы, она выполняет обработку звука в реальном времени.В данном случае этого оказалось достаточно, чтобы Firefox или Windows удерживали Bluetooth-аудиоканал активным, не давая multipoint-наушникам корректно переключиться обратно на телефон.
Похоже на фингерпринтинг
WebAudio-тест — не единственное измерение в этих скриптах. Изучение бандлов обнаружило код, который запрашивает или измеряет:
- рендеринг canvas и toDataURL()
- информацию о WebGL-рендерере, расширениях и точности шейдеров
- вывод аудиоосциллятора и анализатора
- размеры экрана и viewport
- device pixel ratio
- количество ядер и объём памяти устройства
- установленные плагины браузера
- поддерживаемые аудио- и видеоформаты
- поведение WebRTC
- тайминги производительности браузера
- события мыши, тачей, фокуса и скролла
- данные движения и ориентации устройства
- свойства, обычно связанные с автоматизацией браузера
Также присутствует код для сериализации и шифрования результатов, отправки запросов к телеметрическим сервисам Alibaba и передачи данных через fetch() или sendBeacon().
Это довольно полный отпечаток браузера и устройства.
Аудиофингерпринтинг работает потому, что небольшие различия в версиях браузеров, операционных системах, аудиобиблиотеках и оборудовании дают слегка разные результаты обработки одного и того же сгенерированного сигнала. Само по себе этого не всегда достаточно для уникальной идентификации устройства, но в сочетании с данными canvas, WebGL, оборудования, таймингов и взаимодействия ценность резко возрастает.
Что именно AliExpress делает с полученными данными после того, как они попадают на серверы компании — неизвестно. Возможно, они используются как постоянный идентификатор устройства, а возможно — лишь один из параметров в оценке риска мошенничества или бот-активности.
Зачем это нужно AliExpress
У AliExpress достаточно причин отличать обычных покупателей от автоматизированных или подозрительных клиентов, а заодно отслеживать поведение пользователей при просмотре. Площадке приходится бороться с захватом аккаунтов, фейковыми аккаунтами, скрапингом, автоматизированными покупками, платёжным мошенничеством, манипуляциями с отзывами и злоупотреблением купонами и промоакциями для новых клиентов. Как и большинство крупного бизнеса, компания также использует обширные датасеты поведения пользователей для более точного маркетинга товаров и услуг.
Cookie для этой цели не особо надёжны, поскольку их можно очистить, скопировать или подменить. Отпечаток, составленный из множества независимых браузерных измерений, куда сложнее подделать согласованно.
Данные о взаимодействии также помогают определить, управляет ли браузером человек или автоматизация. С точки зрения AliExpress это может снизить мошенничество и позволить доверенным клиентам проходить без показа CAPTCHA на каждой второй странице. (Хотя AliExpress и без того не стесняется собственных CAPTCHA на основе ИИ.)
Идея того, что обычная страница магазина без предупреждения задействует графику, звук, WebRTC, аппаратные датчики и датчики движения для отслеживания поведения, вызывает вопросы — тем более что побочный эффект оказался таким раздражающим: блокировкой музыки. Возможно, если бы AliExpress не мешал слушать музыку, повода разбираться, что делает сайт, вообще бы не возникло.
Блокировка через uBlock Origin
Была протестирована блокировка двух идентифицированных семейств скриптов. При заблокированных обоих запросах главная страница AliExpress продолжила отображаться штатно, а во время контрольного захвата не появилось ни объектов AudioContext, ни подключений к destination.
В Firefox используется официальное расширение uBlock Origin от Raymond Hill. Чтобы заблокировать скрипты, нужно открыть панель uBlock, выбрать «Мои фильтры» и добавить:
! AliExpress AWSC fingerprinting scripts
||assets.aliexpress-media.com/g/AWSC/uab/*/collina.js$script,domain=aliexpress.com
||assets.aliexpress-media.com/g/AWSC/fireyejs/*/fireyejs.js$script,domain=aliexpress.com
Далее нужно нажать «Применить изменения», закрыть все открытые вкладки AliExpress и снова открыть сайт. Закрывать существующие вкладки необходимо, поскольку блокировка скрипта не останавливает аудиоконтекст, который он уже успел создать.
Правила намеренно узкие — они блокируют только два обнаруженных семейства скриптов и только при запросе с AliExpress. Не исключено, что в будущем это перестанет работать, но это отдельный вопрос на будущее.
Поскольку эти скрипты, судя по всему, связаны с антифрод-системами, их блокировка может привести к появлению дополнительных CAPTCHA или проблемам при входе в аккаунт или оформлении заказа. Пока что главная страница и обычный просмотр товаров работают без сбоев, но при отказе AliExpress принять легитимный вход или платёж правила стоит временно отключить.
Почему стоит это блокировать
Антифрод-сценарий понятен, но у этой реализации есть ряд проблем.
Код запускается на обычной странице покупок ещё до совершения какого-либо чувствительного действия. Он собирает широкий набор данных об устройстве и поведении, реализация намеренно затруднена для анализа, а видимых признаков того, что страница запустила живой аудиообрабатывающий граф, нет никаких.
Побочный эффект оказался вполне реальным на аппаратном уровне: тихий тест фингерпринтинга смог вмешаться в переключение Bluetooth multipoint, при этом штатное управление заглушением в браузере не помогало никак.
Если скрытая аналитическая или защитная функция способна настолько плотно завладеть аудиоканалом, что это меняет поведение внешнего оборудования, блокировка такой функции выглядит разумным компромиссом.
Также невозможно проверить, как долго AliExpress хранит отпечаток и используется ли он на других площадках Alibaba. Клиентский код доказывает лишь сбор и передачу обширных фингерпринт-подобных измерений — хранение на стороне сервера и связывание с личностью пользователя из браузера не видны. Можно ли вообще быть уверенным, что кто-то действует в интересах пользователя?
Итог
Главная страница AliExpress тихо создаёт два работающих WebAudio-графа с помощью сильно обфусцированных скриптов безопасности Alibaba. Графы генерируют и анализируют форму волны как часть куда более масштабного браузерного фингерпринта, затем подключаются через узел с нулевым гейном к системному аудио destination, не давая пользователю ничего услышать.
В описанной конфигурации это приводит к тому, что Bluetooth-аудиоканал ПК остаётся активным и не позволяет multipoint-наушникам переключиться обратно на телефон. Заглушение вкладки проблему не решает, поскольку обычного медиаэлемента для заглушения попросту нет.
Блокировка collina.js и fireyejs.js двумя правилами uBlock Origin, приведёнными выше, предотвращает создание скрытых аудиоконтекстов и позволяет спокойно слушать музыку без прерываний при просмотре AliExpress.