浏览器配置文件的外部 URL 安全处理
让外部 URL 行为与所选平台配置保持一致,同时保留标准网页导航。
外部 URL 为什么需要平台策略
操作系统允许应用注册自定义 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 与隐私
协议检测如何工作
协议检测利用浏览器在导航到具有未知或注册自定义方案的 URL 时的行为。已开发出几种技术:
iframe 导航方法:网站创建隐藏 iframe 并将其 src 设置为自定义协议 URL(如 slack://open)。如果 Slack 已安装,浏览器尝试处理导航。如果没有,iframe 接收错误。响应的时间和行为取决于处理器是否存在。
弹出窗口方法:打开 window.open() 到自定义协议 URL 根据处理器注册产生不同行为。在某些浏览器上,弹出窗口被应用处理器消耗。在其他浏览器上,它作为空白窗口保留。
焦点/失焦检测:当协议处理器启动外部应用时,浏览器窗口失去焦点。通过监控 blur 和 focus 事件,网站可以检测应用是否成功启动。
基于时间的检测:浏览器处理协议导航所需的时间取决于处理器是否存在。已安装的处理器比未注册的协议产生更快或更慢的响应(取决于浏览器),这种时间差是可测量的。
浏览器特定行为
不同浏览器以不同方式处理未知协议:
- Chrome:对已知处理器显示询问用户是否打开应用的对话框,对未知协议不做任何操作或显示最小错误。对话框的存在和行为可以被程序化检测。
- Firefox:对注册的协议显示自己的处理器对话框,对未注册的显示错误页面。导航行为揭示处理器注册。
- Safari:已实施限制协议探测的缓解措施,但基于时间的检测在某些场景中仍然有效。
- Edge:与 Chrome 行为类似(基于 Chromium),有额外的协议提示。
Flood Handler 问题
2021 年,研究人员展示了一种名为 "scheme flooding" 的技术,利用协议处理器可靠地跨设备上的多个浏览器进行指纹识别。该技术涉及快速连续测试数十个协议方案并测量响应模式。因为协议处理器是操作系统级注册,指纹在设备上所有浏览器间一致,打败了浏览器级隐私保护。
时间规范化挑战
协议检测的核心挑战是时间。当浏览器处理到自定义协议 URL 的导航时:
- 它检查操作系统协议处理器注册表
- 如果处理器存在,它准备启动应用(或显示提示)
- 如果没有处理器,它回落到错误状态
步骤 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 根据所选配置文件处理外部 URL,避免桌面本地应用改变该配置文件的预期行为。
时间规范化
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 或无自定义应用,协议处理器行为由配置文件控制,而非主机环境。
当前版本的外部 URL 行为
目标为 Android 的浏览器上下文会将不受支持的外部 URL 与桌面宿主应用隔离,标准网页导航仍在上下文中继续。这意味着桌面 worker 上安装的应用不会决定移动配置的行为。
该策略属于上下文。更改目标平台或配置文件后,应创建新上下文。版本验证应确认正常网页流程可以完成,并确认 Android 上下文中的不受支持外部 URL 不会打开桌面应用。
分配配置文件策略
基本 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));
需要检查:
- 已知和未知协议之间的时间差异最小(在噪声范围内)
- 协议探测不触发焦点/失焦事件
- 协议检测测试页面显示统一结果
- 主机安装的应用无法通过协议查询检测
部署保障
-
使用完整配置文件。 协议处理器保护作为一致控制所有指纹面的全面配置文件的一部分效果最好。
-
测试获准的应用流程。 确认网页导航和外部链接行为符合所选平台配置。
-
与其他保护结合。 协议处理器检测通常与 Canvas、WebGL 和字体指纹一起使用。使用完整配置文件确保所有向量都被覆盖。
-
保持配置文件更新。 随着浏览器实施新的协议处理器缓解措施和检测技术演变,更新的配置文件确保持续保护。
-
避免在主机上安装不必要的应用。 虽然 BotBrowser 防止协议泄漏,但最小化主机的已安装应用集可以减少整体攻击面。
外部 URL 问答
协议检测能否识别特定应用版本?
通常不能。协议处理器检测揭示应用是否已安装,而非版本。但一些应用注册版本特定的协议方案,可以缩小版本范围。
协议检测在所有操作系统上工作吗?
该技术在 Windows、macOS 和 Linux 上工作,但具体行为因操作系统而异。BotBrowser 无论主机操作系统如何都规范化行为。
网站能否检测到协议处理器保护?
JavaScript 拦截可能增加页面特定行为。BotBrowser 会在上下文中一致应用所选配置策略。
这会破坏合法协议链接吗?
不会。BotBrowser 的保护针对用于指纹识别的探测行为,而非合法的协议导航。
指纹脚本中可以测试多少个协议?
数量因网站而异,不适合作为部署目标。应验证应用结果,并在版本周期内保持配置文件分配稳定。
这与 "scheme flooding" 攻击相同吗?
Scheme flooding 是协议相关指纹的一种形式。BotBrowser 对外部 URL 应用一致的配置策略。
移动浏览器支持协议检测吗?
是的,但限制更多。移动浏览器(特别是 iOS 上的 Safari)对协议处理器导航有更严格的策略。BotBrowser 的移动配置包含目标移动平台的适当协议处理行为。
registerProtocolHandler() 是否有影响?
navigator.registerProtocolHandler() API 允许网站将自己注册为特定协议的处理器。这与应用安装的协议检测是不同的问题。BotBrowser 作为配置文件的一部分控制检测信号和注册行为。
保持平台行为一致
外部 URL 可能暴露桌面环境信息。BotBrowser 会根据所选平台配置处理它们。Android 上下文将不受支持的 URL 与桌面应用分离,同时保留网页导航。请参阅 Android 模拟文档。