Перейти к содержанию

Вкладка молча забрала звуковую карту: разбор скрытого WebAudio на AliExpress

Опубликовано
  • Админы
Скрытый AudioContext и Bluetooth-мультипойнт
Обычный AudioContext, подключённый к destination, открывает аудиоустройство даже при нулевой громкости

Браузер показывает значок динамика, когда во вкладке что-то играет. Считается, что этого достаточно: нет значка — нет звука — нет и претензий к железу. История, о которой пойдёт речь, ломает именно это допущение.

Жалоба выглядела совсем не как история про приватность. Гарнитура с мультипойнтом держит два подключения сразу — ноутбук и смартфон. Стоит открыть главную AliExpress и оставить вкладку в покое на несколько секунд, как смартфон замолкает. Вкладку закрыли — воспроизведение вернулось. Плеера на странице нет, видео нет, значка динамика тоже нет.

Находку опубликовал 20 августа 2026 года автор блога m-c-tech; эффект воспроизвёлся и в Firefox, и в Chrome под Windows. Дальше — восстановленный ход расследования, который несложно повторить самому.

Подмена конструктора: как увидеть невидимое

Любой звук из JavaScript рождается в графе WebAudio, а граф невозможен без вызова конструктора AudioContext. Отсюда и приём: конструктор заменяется наследником, который перед делом пишет в консоль состояние и стек вызовов.

const OriginalAudioContext = window.AudioContext;
window.AudioContext = class extends OriginalAudioContext {
    constructor(...args) {
        super(...args);
        console.log("AudioContext created", {
            state: this.state,
            stack: new Error().stack
        });
    }
};

Важна очерёдность: код должен отработать раньше скриптов страницы, поэтому его вешают пользовательским скриптом с @run-at document-start. Тем же способом оборачивается AudioNode.prototype.connect() — так становится видно, какие узлы к каким присоединяются.

Консоль выдала два контекста вместо ожидаемого нуля. Оба перешли в состояние running, и стеки обоих упирались в пару файлов с одной раздачи:

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

Под аббревиатурой AWSC у Alibaba скрывается набор антифрод-скриптов. Подтверждение приходит со стороны: в трекере фильтров AdGuard закрыта заявка №199162 по aliexpress.com, и там указан ровно тот же путь — AWSC/uab/1.140.0/collina.js, причём с той же версией.

📌 Заметка

Мультипойнтом называют режим, при котором гарнитура удерживает два активных соединения одновременно. Выбор источника делают не наушники: решает связка операционной системы и профиля A2DP. Открылся аудиопоток с одной стороны — вторая сторона автоматически отходит на второй план.

Пять узлов и ни одной колонки

Граф WebAudio из пяти узлов
Осциллятор, анализатор, ScriptProcessor, гейн на нуле — и выход на звуковую карту

Собранная цепочка оказалась хрестоматийной для звукового отпечатка: пилообразный осциллятор, за ним AnalyserNode, затем ScriptProcessorNode, следом GainNode со значением gain.value = 0 и, наконец, AudioContext.destination.

Смысл конструкции в сравнении входа с выходом. Форма волны на входе известна заранее; пройдя через аудиостек конкретной сборки браузера на конкретном процессоре, она приобретает крошечные отличия за счёт округления чисел с плавающей точкой. Спектр на выходе снимает анализатор — получается устойчивая характеристика устройства. Нулевой гейн добавлен ради того, чтобы человек за экраном ничего не заметил.

Ноль в графе — не ноль в драйвере

Вот здесь и находится развилка, объясняющая поломку. Отпечаток по звуку традиционно снимают через OfflineAudioContext: тот просчитывает буфер быстрее реального времени и до звуковой карты попросту не добирается. Железо в таком сценарии не задействовано никак.

В нашем же случае создаётся полноценный AudioContext, а его последний узел подключён к destination. С точки зрения операционной системы формулировка однозначна: вкладка намерена воспроизводить звук, значит устройство вывода надо открыть. На это решение громкость никак не влияет — она применяется внутри графа, а не в драйвере. Дальше вступает механика мультипойнта: раз поток со стороны компьютера активен, телефон уступает очередь.

🔒 Безопасность

Значок «во вкладке играет звук» при этом не зажигается. Отсюда следует неприятное: средствами интерфейса отличить страницу, молча удерживающую вашу звуковую карту, от любой другой нельзя. Сигналом остаётся только поведение самого устройства.

Обсуждение на Hacker News добавило похожих наблюдений. Владельцы слуховых аппаратов Phonak рассказывают, что отдельные сайты и мобильные приложения на несколько секунд переключают аппарат в режим Bluetooth-стрима, приглушая окружающие звуки. Ещё один участник связал регулярные подвисания Bluetooth-мыши на MacBook со страницей входа American Express. Всё это — реплики в треде, а не измерения, и выдавать их за установленные факты некорректно. Но общее направление они подсказывают: побочный эффект вряд ли ограничен одним магазином.

Что уезжает вместе со звуком

Звуковая характеристика в этом наборе далеко не единственная. Разбор перечисляет также отрисовку canvas вместе с toDataURL(), сведения WebGL — рендерер, расширения, точность шейдеров, — геометрию экрана и вьюпорта, devicePixelRatio, hardwareConcurrency, deviceMemory, перечень плагинов, поддерживаемые контейнеры аудио и видео, повадки WebRTC, тайминги производительности, события мыши, касаний, фокуса и прокрутки, показания акселерометра с гироскопом, плюс маркеры автоматизации браузера. Собранное шифруется и отправляется на серверы Alibaba.

ℹ️ Справка

О назначении забывать не стоит. collina.js и fireyejs.js относятся к антифроду и антиботу, рекламной аналитикой они не являются. Опознание устройства для подобных SDK — основная работа, а не побочный результат. Вопросы это снимает не полностью, зато объясняет само присутствие кода.

Как это выключить

У автора разбора сработали два фильтра uBlock Origin — с ними скрытые контексты просто не появляются:

||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

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

Обойтись без правки фильтров позволяет Firefox. Путь — Настройки → Приватность и защита → Разрешения → Автовоспроизведение, где по умолчанию выставляется «Блокировать аудио», а исключения выдаются точечно нужным сайтам. Есть и крайняя мера: privacy.resistFingerprinting выключает Web Audio API целиком (баг Mozilla 1708593). Платой станут поломанные обычные страницы и повышенная заметность профиля по другим признакам.

⛔ Так делать нельзя

Бесполезно бороться с симптомом на стороне системы — убавлять громкость, отсоединять гарнитуру от компьютера, вручную переставлять приоритеты устройств. Поток остаётся открытым при любом из этих действий, заряд наушников продолжает уходить, а источник проблемы никуда не девается.

И всё-таки сам отпечаток мёртв

Распределение значений звукового отпечатка в телеметрии Firefox
Почти вся аудитория укладывается в три значения — различать по ним некого

Сюжет напрашивался на вывод в духе «WebAudio идёт на смену canvas, срочно защищаемся». До него дело не дошло, и это к лучшему: сутки спустя Том Риттер из Mozilla выложил телеметрию по тому самому признаку.

Распределение такое: в одно из трёх значений укладывается 99,24 % аудитории, оставшиеся 0,76 % — это провалившийся сбор, где вернулся ноль. Хвост состоит из 23 прочих значений на 48 человек. За тройкой лидеров стоят три класса процессоров: x86 и x64 без FMA, x64 с FMA3, ARM с NEON. Отдавать постоянные значения WebAudio Firefox начал в 118-й версии от 26 сентября 2023 года, а Chrome ввёл сопоставимые ограничения ещё раньше. Формулировка Риттера — звуковой отпечаток «почти бесполезен».

❗ Главное

Два сюжета важно не смешивать. Канал утечки энтропии через WebAudio современными браузерами перекрыт, и на различение устройств он почти не работает. Зато возможность страницы без предупреждения занять звуковое устройство и удерживать Bluetooth-канал сохранилась полностью — а расплачивается за неё пользователь батареей гарнитуры и сломанным переключением, вне зависимости от исходных мотивов.

Универсальной защиты тут не появится до тех пор, пока подключение узла к destination не станет для браузеров событием, заслуживающим индикатора. Ровно эту мысль и формулирует Риттер: настораживает не сама техника, а её ненаблюдаемость.


Источники

💬 Вопрос к сообществу

Ведёт ли себя мультипойнт предсказуемо у вас? Хочется собрать перечень сайтов, после которых гарнитура намертво остаётся на компьютере. Поймали такой — повесьте перехватчик AudioContext из первого раздела и покажите стек вызовов.

Featured Replies

No posts to show

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

Последние посетители 0

  • Ни одного зарегистрированного пользователя не просматривает данную страницу
Яндекс.Метрика

Account

Navigation

Поиск

Поиск

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.