
论文: Automatic Discovery of Emerging Browser Fingerprinting Techniques
作者: Junhua Su, Alexandros Kapravelos(NC State University)
发表: WWW '23(The ACM Web Conference 2023)
一、核心发现
在浏览器追踪技术对抗中,风控方总是能迅速采用新颖的浏览器API进行指纹采集,而防守方的检测手段则往往滞后。那么,如何自动、高效地发现这些新兴的指纹技术呢?
这篇由北卡罗来纳州立大学学者发表在WWW‘23的论文,提出了一种全新的自动化解决方案:不再依赖人工一个个去分析哪些浏览器API被用于指纹生成,而是构建了一台名为BFAD(Browser Fingerprinting API Discovery)的自动化指纹API发现引擎。
该论文的核心贡献在于,证实了一个朴素而有效的假设:指纹API在脚本执行时倾向于“扎堆”出现。基于此,研究人员仅以35个已知指纹API为“种子”,对Alexa Top 10K网站进行了大规模爬取与分析。系统会自动识别那些在代码执行顺序上紧邻这些“种子”API的未知API,并通过静态数据流分析确认其返回值是否最终流向了网络传输或本地存储等“出口”,以此判定其是否为新的指纹API。
主要发现如下:
- 第一轮爬取(2021年10月): 发现了 231个指纹API,其中 161个是此前所有检测系统都未曾发现的。
- 第二轮爬取(11个月后,2022年9月): 又新增 18个指纹API,其中15个同样是全新发现。
- 两轮合计: 从最初的35个种子出发,系统共发现了 249个指纹API,数量翻了7倍以上。
这一结果清晰地揭示了一个严峻事实:风控端可利用的指纹武器库远比我们想象的要庞大,并且处于持续、快速的扩张之中。
二、数据拆解
2.1 爬取规模(Table 1)
| 指标 |
数值 |
| 成功爬取域名 |
8,446(Alexa Top 10K) |
| 观测到的Origin |
11,709 |
| 脚本总数 |
474,659 |
| API调用总次数 |
7.54亿次 |
| 去重后的函数调用 |
235,771 |
| 浏览器API调用次数 |
2.18亿次(占总调用约29%) |
| 去重后的浏览器API |
2,333个(占WebIDL规范中7,447个API的31.3%) |
一个关键洞察:脚本数量是域名数的56倍,而Origin数是域名数的1.4倍。这表明现代网页的复杂性极高,单个页面背后可能运行着数十个脚本,指纹采集行为就隐匿在这片脚本的汪洋大海之中。
2.2 发现结果的构成(Table 2)
| 类别 |
数量 |
| 直接指纹API(返回值直接可区分用户) |
90 |
| 间接指纹API(辅助生成指纹,如Canvas绘图API) |
141 |
| URL相关API(辅助数据传输) |
29 |
| Sink API(数据存储/传输出口) |
33 |
| 混淆/反混淆API |
4 |
| 合计验证通过 |
297 |
注意:这里总计297个API(231个指纹API + 66个辅助API)。间接API(141个)的数量远超直接API(90个),这揭示了一个重要趋势:高级指纹技术(如Canvas、WebGL、Audio)的“配套设施”是构成指纹库的大头。如果仅盯着 navigator.userAgent 这类直接API,会漏掉大部分真实的指纹采集行为。
2.3 系统精度
- Locality Calculator初筛:369个API
- 经Fingerprint Analysis(数据流验证)后:323个有sink连接
- 人工验证:297个确认为指纹/辅助API,26个误报
- 误报来源:主要是DOM/HTML相关API(网页本身是DOM与JS的混合体,“邻近性”算法难免捞到一些无关API)。
- 另有18个API因静态分析超时(DFG生成超时5分钟)、Esprima解析错误等原因被系统误拒。
误报率:26/323 ≈ 8.0%——对于一个全自动、大规模的发现系统而言,这个精度已经相当出色。
2.4 新发现API的野外使用情况(Table 3)
| 使用≥N个新发现API的脚本数 |
5个 |
10个 |
15个 |
20个 |
25个 |
30个 |
35个 |
| 脚本数量 |
10,224 |
5,402 |
2,826 |
1,387 |
738 |
444 |
257 |
| 占比 |
81.6% |
43.1% |
22.6% |
11.1% |
5.6% |
3.5% |
2.1% |
在所有12,531个同时执行了至少一个种子API和一个sink API的脚本中,81.6%的脚本使用了5个以上新发现的指纹API。对使用新发现API最多的Top 50脚本进行人工检查,100%被确认为指纹脚本。在已知的792个指纹域名中,平均每个域名执行了 11.5个新发现的指纹API。
2.5 11个月后的纵向对比
第二轮爬取新增了41个API,其中:
- 18个是指纹API(其中15个此前未被任何系统发现)
- 16个是新的sink API
- 7个是DOM相关
这有力证明了BFAD系统具备持续的监控能力:风控技术在不断引入新的API,而该系统能够自动捕获这种技术演进。
三、技术实现
3.1 Locality算法——量化“物以类聚”
核心假设:指纹API在执行序列中总是“扎堆”出现(此前多项研究已证实此现象,且未观察到指纹技术会分散在不同文件中)。
算法逻辑(见论文附录 Listing 1):
- 在API执行序列中,找到连续出现的“种子API”子序列,设其长度为
n。
- 对于子序列周围的邻居API,计算其权重
= n - m,其中 m 是该邻居到最近种子API的距离。
- 如果一个邻居靠近多个种子子序列,则其权重累加。
- 权重
> 0 的API被列为候选。
精妙之处在于搜索范围是数据驱动的。 如果一个脚本中种子API越密集(n 越大),搜索范围会自动扩大;反之则收缩。这有效避免了固定窗口大小带来的“一刀切”问题。
3.2 静态数据流分析——去伪存真
“邻近”不等于“参与指纹”。BFAD使用JStap工具为候选API所在的脚本生成数据流图(DFG),检查该API的返回值是否最终流向了预定义的17个sink(如 WebSocket.send、Window.localStorage 等)。
关键创新在于使用“字符偏移量”来桥接动态与静态分析。 动态分析工具VV8记录了每个API调用在源代码中的字符位置,而JStap生成的DFG节点也关联着字符范围。通过相同的字符偏移量进行对齐,实现了从动态执行序列到静态数据流图的精确映射。这是首次将静态数据流分析系统地应用于浏览器指纹检测领域。
3.3 对VisibleV8(VV8)和JStap的改造
- VV8 原始后处理器只统计API调用频率,丢弃了执行顺序——作者重写了后处理器,保留了完整的API执行序列。
- JStap 原本并不支持指纹分析——作者扩展了JStap,加入了指纹数据流分析逻辑和sink定义。
这两项改造均已开源,为后续研究者提供了可直接复用的工具基础。
四、一些被自动挖掘的指纹实例
论文列举了多个此前未被发现的、正在被实际滥用的指纹API:
History.length:返回当前标签页的浏览历史长度。被Google广告脚本使用,可用于判断用户是直接访问还是从其他页面跳转而来。
ServiceWorkerContainer.controller:检测浏览器是否支持或控制Service Worker。被俄罗斯新闻网站等使用,可结合Performance timing API测量worker启动时间。
MediaQueryList.matches:通过CSS媒体查询检测屏幕尺寸,判断设备类型(如是否为手机)。被taboola等广告平台使用。
PageTransitionEvent.persisted:判断页面是否从浏览器缓存(bfcache)加载。被酷狗音乐、Amazon AWS相关脚本使用。
Permissions API:遍历查询所有权限(摄像头、麦克风、地理位置等)的状态。被eBay等网站用于收集用户设备权限配置。
IntersectionObserver系列API(6个):首次在野外观测到被滥用。用于测量元素在视口中的可见比例和停留时间——这可以有效区分人类用户与自动化Bot(Bot的滚动速度通常不自然,停留时间过于精确)。
MutationObserver系列API(5个):监控DOM变化。如果用户安装了通过修改DOM来实现隐私保护的浏览器扩展,追踪者可以立即察觉到这些变化,反而使该用户变得更加独特。YouTube和Microsoft的脚本已在使用此技术。
Window接口下的41个新API:包括 Window.clientInformation(Window.navigator的冗余访问路径)、Window.ontouchstart(触摸事件)、Window.statusbar.visible(状态栏可见性)等。
五、与现有检测系统的对比
| 系统 |
方法 |
结果格式 |
BFAD覆盖率 |
局限 |
| FP-Inspector |
ML分类脚本级检测 |
JS关键词(仅52.1%是标准API) |
原始种子40.4%,扩展种子81% |
只能检测预选API列表,不监控全量执行 |
| FP-RADAR |
静态分析+“guilt by association” |
313特征(仅公开50个) |
原始种子51%,扩展种子63.6% |
纯静态,无法有效处理混淆/压缩代码 |
| FingerprintAlert |
HTTP传输数据分析 |
286属性(仅22.7%对应浏览器API) |
87.7% |
不涉及JavaScript执行,无法关联到具体API |
BFAD的独家发现:第一轮的161个加上第二轮的15个,共计176个指纹API是此前所有已知检测系统均未发现的盲区。
六、实战建议
给反爬/反指纹开发者(防守方):
- 更新你的API黑名单。 如果你仍在依赖FP-Inspector等工具的旧列表,那么至少遗漏了176个已在野外被滥用的指纹API。建议将BFAD的开源完整列表纳入你的检测规则库。
- 重点关注间接API。 141个间接指纹API的存在表明,追踪者的指纹生成链往往很长。仅拦截
canvas.toDataURL() 可能不够,对Canvas的绘图API、WebGL的状态查询API等都需要进行监控。
- 警惕冗余API路径。
Window.clientInformation 和 Window.navigator 返回相同内容。如果你的检测只hook了其中一个,追踪者使用另一个即可绕过。论文明确指出追踪者正在利用这种冗余性。
- 建立定期重检机制。 11个月就新增18个指纹API,证明武器库在持续扩张。建议至少每季度使用BFAD或类似系统对主流网站进行一次扫描分析。
给爬虫/自动化开发者(攻击方):
IntersectionObserver已成为新的Bot检测利器。 它能精确测量“阅读行为”,如滚动速度和元素停留时间。如果你的自动化脚本不模拟自然的视口交互,很容易被此API识别。
MutationObserver可能正在监控你的反检测手段。 如果你通过注入或修改DOM属性来伪装指纹,请注意,YouTube和Microsoft的脚本已经在使用此API监控DOM变化。
- 注意
Permissions API的遍历查询。 这是新的指纹收集趋势。确保你的无头浏览器或自动化环境的权限配置与真实用户环境保持一致。
给安全架构师与浏览器厂商:
- 在新API发布前进行指纹风险评估。 论文的远景是希望浏览器厂商能持续运行类似BFAD的系统,以评估新特性潜在的指纹滥用风险。
- 在Sink层进行监控可能更高效。 297个指纹/辅助API最终都要通过约50个sink来传输数据。在sink层面进行拦截和管控,是一种“以少御多”的策略。
- 代码混淆无法逃避此类检测。 BFAD的动态分析基于VV8(V8引擎级别的监控),混淆和压缩对其无效。这意味着追踪者不能依赖代码混淆来隐藏其指纹行为。
总结
风控端的指纹武器库是无止境的,因为技术在持续迭代——从35个已知API出发,BFAD自动挖掘出249个,其中176个是所有现有系统的盲区;更关键的是,这个武器库每年都在扩张。
这项研究为对抗不断演进的浏览器指纹技术提供了强有力的自动化工具和新思路。对于从事风控与反风控、隐私保护与追踪技术研究的开发者而言,深入理解BFAD的方法论和发现结果具有重要意义。如果你想就此类技术进行更深入的探讨,欢迎在云栈社区相关板块交流。