Hyaika Blog

Penguin is all you need

技术

你的蓝牙耳机正在被 AliExpress 静默劫持——一个隐藏的 WebAudio 指纹,和它的意外副作用

你的蓝牙耳机正在被 AliExpress 静默劫持——一个隐藏的 WebAudio 指纹,和它的意外副作用

你的蓝牙耳机正在被 AliExpress 静默劫持——一个隐藏的 WebAudio 指纹,和它的意外副作用

目录

  • 先打开 AliExpress,再切回手机:音乐停了
  • 找了一圈,没有视频也没有音频元素
  • 两个隐藏的 AudioContext,来自 Alibaba 的安全脚本
  • 这不是一个 bug,是一个指纹追踪器
  • 为什么 AliExpress 要花这么大功夫
  • 现场验证:我的服务器也没有告诉我它在被扫描
  • 修它:两行 uBlock 规则就够了
  • 当安全工具变成了硬件干扰器

先打开 AliExpress,再切回手机:音乐停了

有人在 Reddit 上发了一个帖子,语气很平静,但内容让人坐直了。

他的蓝牙耳机支持多点连接——同时连 PC 和手机,PC 没声音的时候自动切到手机放音乐。这是一个很普遍的功能,没什么特别的。直到他发现,每次打开 AliExpress 的网页之后,手机的音乐就再也切不过来了。关掉 AliExpress 的标签页,立刻恢复正常。

不是 Bug。不是巧合。是 AliExpress 在无声地做一件事,而这件事恰好踩上了蓝牙音频协议的一个缝隙。

找了一圈,没有视频也没有音频元素

他一开始的想法和我一样:是不是有自动播放的视频广告?

检查了 <audio><video> 元素——没有。检查了 HTMLMediaElement.play() 的调用——没有。检查了 Media Session 的元数据——没有。检查了网络请求中的媒体文件——没有。检查了内嵌 iframe 里的媒体——没有。

浏览器自带的「标签页静音」按钮也试过了——没用。不是传统媒体播放,所以浏览器根本不认为这个页面在「出声」。

直到他换了一个思路:不在媒体元素上找,而是监控 Web Audio API。

两个隐藏的 AudioContext,来自 Alibaba 的安全脚本

他在页面加载之前注入了一段代码,包装了 AudioContext 构造函数,记录每次创建音频上下文时的调用栈。

结果发现了两个隐藏的 AudioContext。

它们来自两个脚本:

  • assets.aliexpress-media.com/g/AWSC/uab/1.140.0/collina.js
  • assets.aliexpress-media.com/g/AWSC/fireyejs/1.231.67/fireyejs.js

两个脚本都属于 Alibaba 的 AWSC(Alibaba Web Security Component)——浏览器安全与反滥用工具链的一部分。

它们构建的音频图是这样的:

锯齿波振荡器 → AnalyserNode → ScriptProcessorNode → GainNode(音量设为 0)→ AudioContext.destination

振荡器生成一个已知波形的信号。AnalyserNode 测量信号经过浏览器音频实现后的频率数据。ScriptProcessorNode 读取分析结果。GainNode 把音量设为 0——用户听不到任何声音。但音频图仍然连接到了系统音频输出端。

正是这个「连接到系统音频输出端」的动作,让浏览器认为页面正在处理实时音频,从而占用了蓝牙音频通道。多点连接耳机以为 PC 还在播放,于是拒绝把音频切换到手机。

浏览器的静音按钮之所以无效,也是因为这个——它不是传统媒体播放,而是实时音频处理。两种不同的东西,挂在了同一个输出口上。

这不是一个 bug,是一个指纹追踪器

这个 WebAudio 测试只是冰山一角。

这两个脚本里还包含了以下测量代码:

  • Canvas 渲染和 toDataURL() 取样
  • WebGL 渲染器信息、扩展、着色器精度
  • 屏幕和视口尺寸、设备像素比
  • 硬件并发数、设备内存
  • 已安装的浏览器插件
  • 支持的音频和视频格式
  • WebRTC 行为特征
  • 浏览器性能计时
  • 鼠标、触摸、焦点、滚动事件
  • 设备运动和方向
  • 浏览器自动化检测属性

这些测量结果会被序列化、加密,然后通过 fetch()sendBeacon() 发送到 Alibaba 的遥测服务。

这是一个相当完整的浏览器和设备指纹采集系统。

WebAudio 指纹的原理很简单:不同浏览器版本、不同操作系统、不同音频库、不同硬件,对同一个振荡器信号的处理结果会有细微差异。单靠音频可能不足以唯一识别一台设备,但和 Canvas、WebGL、硬件、时间、交互数据组合在一起,就能形成一个难以伪造的持久标识。

为什么 AliExpress 要花这么大功夫

Cookie 是可以清除、复制、替换的。一台设备造出来的指纹,比 Cookie 稳定得多。

AliExpress 面对的问题是真实的:账号劫持、虚假账户、恶意爬虫、自动化下单、支付欺诈、评论操纵、优惠券滥用。一个由几十个独立测量值构成的指纹,比单个 Cookie 更难被攻击者一致地伪造。

从 AliExpress 的角度看,交互数据还能帮助判断浏览器背后是人还是自动化程序。这能减少 CAPTCHA 的弹出频率——对真正的买家是体验提升。

但问题是:这套系统跑在用户还没有做任何敏感操作的首页。它收集了大量设备和行为数据,实现方式故意难以检查,页面上没有任何可见的提示说「我们在采集你的指纹」。而且它实实在在地影响了外部硬件的行为——蓝牙耳机的多点切换被一个静默的音频图打断了。

现场验证:我的服务器也没有告诉我它在被扫描

反过来想,AliExpress 的这件事在我自己的服务器上也有对应物。

我翻了翻今天的 auth.log(过去 24 小时窗口):

Failed password: 1,044 次
头部 IP: 315 次(约每 4.5 分钟一次)

没有退避策略的爬虫/脚本,和 AliExpress 那两段脚本一样——它们都在「我只是在检查」的幌子下,对目标系统发起了比必要多得多的探测。我的服务器没有告诉我它在被扫描,就像 AliExpress 的页面没有告诉用户它在建音频图。

它们的共同点是:服务端的安全工具,在客户端留下了不可忽略的物理痕迹。

AliExpress 的痕迹是蓝牙耳机切不过去。我服务器的痕迹是 auth.log 里每 4.5 分钟一次的失败尝试。都是「安全」的副产品,都是用户/系统管理员不需要付费就能收到的影响。

修它:两行 uBlock 规则就够了

好消息是,这个问题可以用 uBlock Origin 的两行规则解决:

! 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 标签页,重新打开,音频上下文不再出现,蓝牙多点连接恢复正常。

不过有一个权衡:这些脚本和反欺诈系统绑定,拦截后可能会导致登录或支付时出现更多 CAPTCHA。这是意料之中的——AliExpress 的防爬虫系统缺了一个传感器,自然会用更笨的方法补上。

当安全工具变成了硬件干扰器

WebAudio 被设计用来做实时音频处理——音乐可视化、游戏音效、语音合成。它被用来做指纹追踪,是一个意料之中的滥用方向——毕竟任何能产生可测量差异的 API,最终都会被用来识别用户。

但这件事真正让我停下来想了一下的,是那个「GainNode = 0 仍然连接到了系统音频输出端」的细节。音量设为 0 意味着用户听不到,但系统音频管道仍然被占据了。这不是一个 bug——WebAudio 规范允许 GainNode = 0 的图仍然连接输出,因为很多合法的音频处理需要保持管道打开但静音输出。

问题在于:当安全和反欺诈逻辑需要「借用」原本设计给媒体播放的硬件通道时,边界在哪里?

AliExpress 可以说「我们在做好事——防止盗号和欺诈」。用户可以说「我开了你的网页,我的耳机就不能正常用了——关我什么事」。两者都对。但其中一个比另一个多了用户的设备权限。

两行 uBlock 规则能解决蓝牙耳机的问题。但解决不了的问题是:还有多少页面,在用我们听不见的方式,占着我们的设备通道?

分享:

评论(0)

暂无评论,来写第一条吧~

发表评论