指纹

协议处理器检测:检测已安装应用

mailto: 和 slack: 等 URL 协议处理器如何揭示已安装应用用于指纹识别,以及如何控制协议响应。

文档中心

想直接进入 指纹 文档吗?

这篇文章属于博客内容库。若你要步骤化配置、参考说明和持续更新,请直接进入对应 docs 分区。

简介

操作系统允许应用注册自定义 URL 方案,也称为协议处理器。当 Slack、VS Code、Zoom 或 Steam 等应用安装后,它会注册一个协议(如 slack://vscode://zoommtg://steam://),使其他应用和网站能够通过 URL 直接启动它。这个系统支持深度链接,允许网站打开特定应用视图、加入会议或通过简单的链接点击启动游戏。

然而,使协议处理器有用的机制也使它们成为指纹面。网站可以尝试导航到自定义协议 URL 并观察浏览器的响应。行为取决于协议关联的应用是否已安装:浏览器可能显示打开应用的提示、静默重定向、显示错误或什么都不做。通过测试已知协议方案列表,网站可以构建访客设备上安装了哪些应用的配置文件,创建高度独特的指纹。

隐私影响

基于协议的应用检测是最侵犯隐私的指纹技术之一,因为它揭示的是用户软件环境而非硬件的信息。虽然硬件指纹识别设备,应用指纹识别的是人及其活动。

隐私影响显著:

  • 软件清单:通过测试常见协议处理器(Spotify、Discord、Telegram、WhatsApp、Steam、Epic Games、Zoom、Teams、VS Code、Sublime Text 等数十种),网站可以确定哪些应用已安装。
  • 行为分析:已安装的应用揭示兴趣、职业和行为模式。有 vscode://iterm2://docker:// 的开发者与有 steam://epicgames://discord:// 的游戏玩家呈现不同的配置。
  • 设备唯一性:已安装应用的特定组合高度独特。即使在硬件相同的设备中,安装的软件集在用户间差异很大。
  • 跨浏览器追踪:协议处理器在操作系统级别注册,而非浏览器级别。这意味着相同的应用指纹在设备上所有浏览器间持续存在,实现跨浏览器追踪。

2021 年 FingerprintJS 的一项里程碑研究表明,基于协议的指纹识别可以在几秒内测试 32 个流行应用,产生唯一识别 95% 测试对象的指纹。该技术跨 Chrome、Firefox、Edge 和其他浏览器工作。该研究促使浏览器厂商开始实施缓解措施,但基本漏洞在许多场景中仍然存在。

该技术特别令人担忧,因为它不需要权限且可以静默执行。用户不会收到其已安装应用正在被探测的通知。

技术背景

协议检测如何工作

协议检测利用浏览器在导航到具有未知或注册自定义方案的 URL 时的行为。已开发出几种技术:

iframe 导航方法:网站创建隐藏 iframe 并将其 src 设置为自定义协议 URL(如 slack://open)。如果 Slack 已安装,浏览器尝试处理导航。如果没有,iframe 接收错误。响应的时间和行为取决于处理器是否存在。

弹出窗口方法:打开 window.open() 到自定义协议 URL 根据处理器注册产生不同行为。在某些浏览器上,弹出窗口被应用处理器消耗。在其他浏览器上,它作为空白窗口保留。

焦点/失焦检测:当协议处理器启动外部应用时,浏览器窗口失去焦点。通过监控 blurfocus 事件,网站可以检测应用是否成功启动。

基于时间的检测:浏览器处理协议导航所需的时间取决于处理器是否存在。已安装的处理器比未注册的协议产生更快或更慢的响应(取决于浏览器),这种时间差是可测量的。

浏览器特定行为

不同浏览器以不同方式处理未知协议:

  • Chrome:对已知处理器显示询问用户是否打开应用的对话框,对未知协议不做任何操作或显示最小错误。对话框的存在和行为可以被程序化检测。
  • Firefox:对注册的协议显示自己的处理器对话框,对未注册的显示错误页面。导航行为揭示处理器注册。
  • Safari:已实施限制协议探测的缓解措施,但基于时间的检测在某些场景中仍然有效。
  • Edge:与 Chrome 行为类似(基于 Chromium),有额外的协议提示。

Flood Handler 问题

2021 年,研究人员展示了一种名为 "scheme flooding" 的技术,利用协议处理器可靠地跨设备上的多个浏览器进行指纹识别。该技术涉及快速连续测试数十个协议方案并测量响应模式。因为协议处理器是操作系统级注册,指纹在设备上所有浏览器间一致,打败了浏览器级隐私保护。

时间规范化挑战

协议检测的核心挑战是时间。当浏览器处理到自定义协议 URL 的导航时:

  1. 它检查操作系统协议处理器注册表
  2. 如果处理器存在,它准备启动应用(或显示提示)
  3. 如果没有处理器,它回落到错误状态

步骤 2 和 3 需要不同的时间量,这种时间差异是主要信号。即使浏览器尝试规范化可见行为(对两种情况显示相同 UI),底层处理时间通常不同。

常用协议列表

指纹脚本中测试的常见协议包括:

  • 通信:slack://discord://telegram://whatsapp://signal://
  • 开发:vscode://sublime://atom://docker://
  • 游戏:steam://epicgames://uplay://
  • 生产力:notion://evernote://todoist://
  • 媒体:spotify://vlc://figma://
  • 会议:zoommtg://msteams://webex://

测试 30-40 个协议产生足够独特的组合以进行可靠识别。

常见保护方法及其局限性

VPN 和代理服务器

VPN 对协议处理器检测没有影响。协议注册是本地操作系统属性,检测完全在浏览器内发生。

隐身和隐私浏览

隐私浏览模式不改变协议处理器注册。因为协议处理器在操作系统级别注册,而非浏览器配置文件中。

浏览器扩展

扩展可以尝试拦截协议导航:

  • 阻止 iframe 导航:扩展可以阻止 iframe 中的所有自定义协议导航,但这会破坏合法的深度链接且容易检测,因为阻止行为本身是可观察的。
  • 规范化时间:扩展可以为所有协议导航添加延迟以规范化时间,但扩展拦截的开销本身是可检测的,延迟必须仔细校准以避免破坏合法的协议链接。
  • 禁用弹出窗口:阻止自定义协议的 window.open() 防止了一种检测方法但破坏了合法的应用启动。

浏览器缓解措施

现代浏览器已实施一些保护:Chrome 添加了协议处理器检查的速率限制,Safari 实施了更严格的同源策略,Firefox 为某些协议导航方法添加了用户手势要求。这些缓解减少了快速协议探测的有效性,但不消除使检测成为可能的根本时间差异。

BotBrowser 的引擎级方法

BotBrowser 在浏览器引擎级别控制协议处理器行为,确保所有协议导航尝试产生统一响应,无论主机系统上实际安装了哪些应用。

时间规范化

BotBrowser 规范化协议导航处理的时间,使注册和未注册的协议产生不可区分的时间签名。这消除了基于协议指纹识别中使用的主要信号:

chrome --bot-profile="/path/to/profile.enc" \
       --user-data-dir="$(mktemp -d)"

统一行为响应

除了时间之外,BotBrowser 确保可观察行为(错误状态、焦点/失焦事件、iframe 状态)对所有协议导航尝试一致。浏览器不通过任何行为渠道揭示处理器是否存在。

合法协议链接

保护不完全阻止协议导航。当用户或自动化脚本作为正常工作流程的一部分显式跟随协议链接时,导航正常进行。只有探测行为(通过时间和行为分析快速枚举协议处理器)被中和。

配置文件集成

协议处理器保护是更广泛指纹配置文件的一部分。它与操作系统识别、浏览器版本信号和其他平台特定行为一起工作以维护一致的身份:

chrome --bot-profile="/path/to/profile.enc" \
       --bot-noise-seed=42 \
       --proxy-server="socks5://user:pass@proxy:1080" \
       --user-data-dir="$(mktemp -d)"

无主机环境泄漏

关键保证是主机的已安装应用不通过协议处理器查询泄漏。无论主机是否安装了 Slack、Steam、VS Code 或无自定义应用,协议处理器行为由配置文件控制,而非主机环境。

配置和使用

基本 CLI 用法

加载配置文件时自动提供协议处理器保护:

chrome --bot-profile="/path/to/profile.enc" \
       --user-data-dir="$(mktemp -d)"

Playwright 集成

const { chromium } = require('playwright-core');

(async () => {
  const browser = await chromium.launch({
    executablePath: '/path/to/botbrowser/chrome',
    args: ['--bot-profile=/path/to/profile.enc'],
    headless: true,
  });

  const context = await browser.newContext({ viewport: null });
  const page = await context.newPage();

  await page.goto('https://example.com');
  // 协议处理器查询将产生统一响应
  // 无论主机安装了哪些应用
  await browser.close();
})();

Puppeteer 集成

const puppeteer = require('puppeteer-core');

(async () => {
  const browser = await puppeteer.launch({
    executablePath: '/path/to/botbrowser/chrome',
    args: ['--bot-profile=/path/to/profile.enc'],
    headless: true,
    defaultViewport: null,
  });

  const page = await browser.newPage();
  await page.goto('https://example.com');
  // 协议处理器信号由配置文件控制
  await browser.close();
})();

与应用身份保护结合

为获得完整的应用级隐私:

chrome --bot-profile="/path/to/profile.enc" \
       --bot-noise-seed=42 \
       --bot-config-timezone="Europe/London" \
       --bot-config-locale="en-GB" \
       --user-data-dir="$(mktemp -d)"

验证

使用配置文件启动 BotBrowser 后,验证协议处理器保护:

// 测试协议处理器时间一致性
async function testProtocolTiming(protocol) {
  const start = performance.now();
  const iframe = document.createElement('iframe');
  iframe.style.display = 'none';
  document.body.appendChild(iframe);

  return new Promise(resolve => {
    iframe.onload = () => {
      resolve(performance.now() - start);
      document.body.removeChild(iframe);
    };
    iframe.onerror = () => {
      resolve(performance.now() - start);
      document.body.removeChild(iframe);
    };
    iframe.src = `${protocol}://test`;
    setTimeout(() => {
      resolve(performance.now() - start);
      if (iframe.parentNode) document.body.removeChild(iframe);
    }, 500);
  });
}

// 注册和未注册的协议都应产生相似时间
const timing1 = await testProtocolTiming('slack');
const timing2 = await testProtocolTiming('nonexistentprotocol12345');
console.log('Slack timing:', timing1);
console.log('Unknown protocol timing:', timing2);
console.log('Difference:', Math.abs(timing1 - timing2));

需要检查:

  1. 已知和未知协议之间的时间差异最小(在噪声范围内)
  2. 协议探测不触发焦点/失焦事件
  3. 协议检测测试页面显示统一结果
  4. 主机安装的应用无法通过协议查询检测

最佳实践

  1. 使用完整配置文件。 协议处理器保护作为一致控制所有指纹面的全面配置文件的一部分效果最好。

  2. 针对已知检测方法测试。 访问协议指纹测试页面验证你的配置不泄漏安装的应用信息。

  3. 与其他保护结合。 协议处理器检测通常与 Canvas、WebGL 和字体指纹一起使用。使用完整配置文件确保所有向量都被覆盖。

  4. 保持配置文件更新。 随着浏览器实施新的协议处理器缓解措施和检测技术演变,更新的配置文件确保持续保护。

  5. 避免在主机上安装不必要的应用。 虽然 BotBrowser 防止协议泄漏,但最小化主机的已安装应用集可以减少整体攻击面。

常见问题

协议检测能否识别特定应用版本?

通常不能。协议处理器检测揭示应用是否已安装,而非版本。但一些应用注册版本特定的协议方案,可以缩小版本范围。

协议检测在所有操作系统上工作吗?

该技术在 Windows、macOS 和 Linux 上工作,但具体行为因操作系统而异。BotBrowser 无论主机操作系统如何都规范化行为。

网站能否检测到协议处理器保护?

如果保护在 JavaScript 级别应用(拦截导航事件),拦截本身可被检测。BotBrowser 在引擎级别应用保护,使规范化对页面脚本不可见。

这会破坏合法协议链接吗?

不会。BotBrowser 的保护针对用于指纹识别的探测行为,而非合法的协议导航。

指纹脚本中可以测试多少个协议?

现代指纹脚本测试 20-40 个常见协议处理器。每个测试大约需要 100-500ms。BotBrowser 的时间规范化使所有测试产生不可区分的结果。

这与 "scheme flooding" 攻击相同吗?

Scheme flooding 是 2021 年演示的基于协议指纹识别的一个特定实现。BotBrowser 的协议处理器保护通过控制底层引擎级行为来解决 scheme flooding 和所有其他协议检测方法。

移动浏览器支持协议检测吗?

是的,但限制更多。移动浏览器(特别是 iOS 上的 Safari)对协议处理器导航有更严格的策略。BotBrowser 的移动配置包含目标移动平台的适当协议处理行为。

registerProtocolHandler() 是否有影响?

navigator.registerProtocolHandler() API 允许网站将自己注册为特定协议的处理器。这与应用安装的协议检测是不同的问题。BotBrowser 作为配置文件的一部分控制检测信号和注册行为。

总结

自定义 URL 协议处理器暴露用户的已安装应用清单,创建最独特的指纹面之一。该技术跨浏览器工作,在隐私浏览模式中持续存在,并揭示关于用户活动和兴趣的个人信息。BotBrowser 在浏览器引擎级别控制协议处理器行为,规范化时间和行为响应,使已安装应用无法通过协议探测被检测。相关保护请参阅 Navigator 属性保护字体指纹控制全面配置文件管理

#Url#Protocol#Handler#浏览器指纹识别#Privacy#Application-Detection

让 BotBrowser 从研究走向生产

先用这些指南理解模型,再进入跨平台验证、隔离上下文和面向规模化的浏览器部署。