数字“指纹”收集

数字“指纹”收集是指在用户回访您的网站时尝试识别用户的身份,或跨不同网站识别同一用户。 您的设置与其他人的设置在很多方面可能有所不同。例如,您可能使用不同类型的设备和浏览器,具有不同的屏幕尺寸,并且安装了不同的字体。如果我安装了“Dejavu Sans”字体,但您没有安装,那么任何网站都可以通过检查该字体来辨别您和我之间的不同之处。数字“指纹”收集的工作原理就是如此;您构建了这些数据点的集合,且每种数据点都提供了更多区分用户的方法。

更正式的定义可能如下所示:数字“指纹”收集是指利用用户设置长期存在的显而易见的特征,尝试将其与尽可能多的其他用户区分开来。

为什么数字“指纹”收集会妨碍用户隐私

在一些极端情况下,对用户进行指纹识别非常重要,例如欺诈检测。但数字“指纹”收集也可用于跨网站跟踪用户,而且这种跟踪通常是在未经用户同意的情况下进行的,或者在某些情况下基于未充分告知用户的无效同意情况进行的跟踪。这样做的话,这些用户往往会觉得这有些令人不安,并感觉遭到背叛了。

数字“指纹”收集是指设法隐秘地区分不同用户。数字“指纹”收集可用于识别用户仍是同一网站上的同一用户,也可用于同时在两个不同的浏览器个人资料中识别同一用户。这意味着,可以使用数字“指纹”收集来跨网站跟踪用户。确定性和公开的跟踪方法(例如存储具有用户专属 ID 的 Cookie)在某种程度上可由用户观察和控制(前一单元介绍了其中一些方法)。但数字“指纹”收集较为难以避免,因为它具有隐秘性;它依赖于不变的特征,并且很可能是在无形的情况下发生的。这就是所谓的“数字“指纹”收集。无论是数字指纹还是手指末端的指纹,都是很难更改指纹的。

浏览器供应商知道用户不喜欢被跟踪,因此一直在实现限制数字“指纹”收集的功能(我们在上一单元中见到了一些功能)。在这里,我们将了解这些功能如何影响您的业务需求,以及如何以保护隐私的方式执行您想要执行的操作。这更重要的是,防范浏览器保护功能将如何影响您执行的操作和操作方式,而不是如何阻止您执行数字“指纹”收集操作。

在实践中,大多数开发者和大多数企业都不需要对用户进行指纹识别。如果您的应用要求用户登录,那么用户就是在征得用户同意,并能够随时单方面选择退出登录。这是一种用于了解哪些用户登录的隐私保护方法。您的应用可能根本不需要用户登录,这可以更好地保护用户的隐私(这样,您就会只收集所需的数据)。

正确做法

评估您的第三方进行数字“指纹”收集。作为第三方模块的一部分,您可能已经有包含的任何第三方服务及其发出的 Web 请求的列表。您可以检查这些请求,了解哪些数据正在传回给发起者(如果有)。然而,这往往很困难;数字“指纹”收集本质上是一个隐蔽的过程,涉及请求无需用户批准的数据。

此外,还建议您阅读第三方服务和依赖项的隐私权政策,看看有没有使用数字“指纹”收集方法的迹象。它有时称为“概率匹配”,或作为一套概率匹配技术的一部分,而不是“确定性匹配”。

数字“指纹”收集的工作原理

通常,所有这些属性的个人组合都是您独有的,或者至少是一小群类似人所独有;这可用于暗中跟踪您。

补充内容:被动式数字“指纹”收集和主动式数字“指纹”收集

这里对被动数字“指纹”收集技术和主动数字“指纹”收集技术有一个实用区别。被动数字“指纹”收集技术是指默认向网站提供的信息;主动数字“指纹”收集技术用于明确询问浏览器以获取额外信息。这种区别之所以重要,是因为浏览器可以尝试检测和拦截或缓解主动技术。可以限制 API,或者在询问用户权限的对话框后面设置网关(从而提醒用户正在使用 API,或允许用户默认拒绝它们)。被动技术使用已经提供给网站的数据,这通常是因为在信息快速发展的初期阶段,这些信息会提供给所有网站。用户代理字符串就是一个示例,稍后我们会对其进行更详细的介绍。它被认为在提供大量有关用户浏览器、版本和操作系统的信息方面很有用,网站可以根据这些信息选择显示不同的内容。但是,这也增加了提供的区分信息的数量,有助于区分不同用户的信息;因此,此类信息越来越多地不再可用,或至少冻结,这样它就不再能够进行区分。如果您的操作依赖于这些信息(例如,如果您根据用户代理采用不同的代码分支),那么随着浏览器越来越多地冻结或停止该信息,此代码可能会中断。测试是这里的最佳防御措施(详见下文)。

补充:衡量指纹性

用来衡量这些数据点提供多少信息的技术度量称为,以位为单位进行测量。具有许多不同可能值的功能(例如安装的字体列表)可能会在总值中占用很多位,因此区分能力不够强的功能(例如您使用的操作系统)可能只会增加少量值。HTTP 年历描述了现有的指纹库如何自动执行这一过程:将来自许多不同 API 的响应合并到一个“哈希”中,该哈希可能只能识别一小部分用户,甚至可能只有一个用户。Maud Nalpas 在这个 YouTube 视频中对这一点进行了详细介绍,但简而言之,想象一下,你看到的是朋友列表,其中包含他们最喜欢的音乐、最喜欢的食物和他们使用的语言...但他们的名字已被移除。很有可能任何一个人的列表在您的朋友中唯一地标识他们,或者至少将列表范围缩小到只有几个人。数字“指纹”收集的工作原理就是如此;您喜欢的列表即会成为“哈希”。有了该哈希,就可以更轻松地在两个未关联的网站上将某位用户识别为同一个人,而跟踪目的就是要规避用户追求隐私的意愿。

浏览器如何防范数字“指纹”收集?

重要的是,浏览器供应商非常清楚,网站(或网站中包含的第三方)可通过多种不同方式计算用户的辨识指纹,或者通过不同的信息来判断指纹的唯一性。其中一些方式是明确而刻意的,例如浏览器的用户代理字符串,该字符串通常用于标识正在使用的浏览器、操作系统和版本(如果您和我使用不同的浏览器,这样做有助于将您与我区分开来)。有些方式并非刻意创建为可指纹识别,但最终还是如此,例如字体列表或浏览器可用的视频和音频设备。(浏览器不一定要使用这些设备,只需按名称获取设备列表即可。)其中一些已确定为在指纹发布后形成的贡献者,例如在画布元素上对字体抗锯齿的精确像素渲染。还有很多其他功能,而您的浏览器与我的浏览器与我的浏览器的不同之处都会增加熵,因此可能有助于区分您和我之间的不同,并在各个网站上尽可能唯一地识别个人。https://amiunique.org 包含很多可能影响指纹的功能,但非常不全面,如果用户不想要指纹贡献,那么此名单可能会一直增加,因为即使用户不愿意花很多金钱,也可能会越来越多的金钱。

不支持某些强大的 API

浏览器供应商对所有这些计算用户指纹的方法的响应是想方设法减少这些 API 提供的熵量。限制性最强的方案就是一开始就不要实现它们。一些主流浏览器已经针对各种硬件和设备 API(例如,从客户端 Web 应用进行 NFC 和蓝牙访问)实现了这一目的,并指出数字“指纹”收集和隐私问题是未实现这些 API 的原因。显然,这可能会影响您的应用和服务:您不能在没有实现某个 API 的浏览器中使用该 API,这可能会限制或完全阻止某些硬件方法的考虑。

用户权限网关

浏览器供应商采取的第二种方法是阻止在未获得某种明确用户许可的情况下访问 API 或数据。 这种做法通常也是出于安全考虑:未经您的许可,网站不应无法使用您的摄像头拍照!但在这里,隐私和安全可能具有相似的兴趣。当然,识别某人的位置信息本身就是侵犯隐私权的行为,但也有助于提高指纹的唯一性。要求查看地理定位不会减少位置增加该指纹唯一性的额外熵,但基本上可以避免使用地理定位进行数字“指纹”收集,因为这种操作是以隐藏方式进行的。数字“指纹”收集的核心就是秘密地将用户与其他用户区分开来。如果您已准备好让用户知道您正在尝试识别他们,则不需要使用数字“指纹”收集技术:让用户创建帐号并登录。

增加不可预测性

在某些情况下,浏览器供应商可以对 API 的响应进行“模糊测试”,降低响应的精细度,从而降低识别率。这是数据模块中随机响应机制的一部分。在从用户处收集数据时,您可以采取一些措施,以免无意中收集身份识别数据。浏览器供应商也可以采用此方法,获取提供给 Web 应用和第三方的 API 数据。例如,从 window.performance.now() 开始用于衡量网页性能的非常准确的计时 API。浏览器知道这些值的精度为微秒,但返回的值会被刻意降低精度,方法是将这些值四舍五入为最接近的 20 微秒边界,以避免将其用于数字“指纹”收集(当然也是为了保证安全性,避免时间攻击)。这样做的目的是确保 API 仍然有用,但降低响应的识别性:实质上,通过使您的设备看起来更像其他人的设备,而不是您特有的设备,来提供“群免免疫”。正因如此,Safari 提供了简化版本的系统配置

强制执行隐私预算

隐私预算是一项提案,建议浏览器估算每个指纹表面会披露的信息。但浏览器尚未实现此功能。目的是在保护用户隐私的同时启用功能强大的 API。详细了解隐私预算提案

使用广泛的测试环境

所有这些因素都将影响您开发应用和服务的方式。特别是在这一方面,针对不同浏览器和平台的响应和处理方法非常多样化。这意味着,在多个不同环境中测试您的工作至关重要。当然,这始终很重要,但可以合理地假设,无论引擎在哪个浏览器或平台上,HTML 呈现或 CSS 对给定呈现引擎而言都是恒定的(因此,人们往往倾向于只在一个基于 Blink 的浏览器中进行测试)。对于 API 的使用来说,这并不是一项确切的 API 使用案例,因为共用一个渲染引擎的浏览器在强化 API Surface 以防范数字“指纹”收集的方式上可能会有很大的差异。

正确做法

  • 根据您自己的分析数据和受众群体来判断测试时应优先考虑哪些浏览器。
  • 适合测试的浏览器包括 Firefox、Chrome、Edge、桌面设备上的 Safari、Android 上的 Chrome 和 Samsung Internet 以及 iOS 上的 Safari。这可确保您在三大主要渲染引擎(Firefox 中的 Gecko、Chrome、Edge 和 Samsung Internet 中的各种 Blink 以及 Safari 中的 Webkit)上进行测试,并在移动平台和桌面平台上进行测试。
  • 如果您的网站还可能在用户不常用的设备(例如平板电脑、智能手表或游戏机)上使用,也请在您的设备上进行测试。 某些硬件平台在浏览器更新方面可能落后于移动设备和桌面设备,这意味着某些 API 可能未实现或无法在这些平台上的浏览器中使用。
  • 使用一个或多个声称用户隐私作为动力的浏览器进行测试。在可行且可行的情况下,为最常见的浏览器添加即将发布的预发布版本和测试版本:Safari 的技术预览、Chrome 的 Canary 版本、Firefox 的 Beta 渠道。通过这些变更,您可以在这些变更影响到用户之前,最有可能找出影响您网站的 API 损坏和变更。同样,在使用任何分析数据时都要考虑用户的环境。如果您的用户群拥有大量旧版 Android 手机,请务必在测试中包含这些手机。大多数人都没有开发团队那样的快速硬件和最新版本。
  • 使用简洁个人资料和无痕模式/无痕浏览模式进行测试;可能是因为您已在个人资料中授予了所需权限。测试如果您拒绝向网站授予任何问题,会发生什么情况。
  • 在 Firefox 的指纹保护模式下明确测试您的网页。这样一来,如果您的网页尝试数字“指纹”收集,或者会返回某些 API 的模糊数据,系统就会显示权限对话框。 这有助于您确认服务中包含的第三方使用的是可指纹的数据,还是您自己的服务依赖于可指纹的数据。然后,就可以考虑刻意的模糊测试是否会导致更难以执行所需操作。请考虑相应地做出更正,以便从其他来源获取该数据、不获取这些数据或使用更精细的数据。
  • 第三方模块中所述,审核第三方依赖项以查看它们是否使用了数字“指纹”收集技术也很重要。被动数字“指纹”收集很难检测(如果第三方在其服务器上做到这一点,则无法做到这一点),但数字“指纹”收集模式可能会标记一些数字“指纹”收集技术,并且寻找使用 navigator.userAgent 或意外创建 <canvas> 对象或许能发现一些应该进一步审查的方法。您也可以在描述第三方的营销或技术材料中寻找使用“概率匹配”一词的情况;这有时可能表明是否使用了数字“指纹”收集技术。

跨浏览器测试工具

出于隐私保护目的测试代码很难实现自动化,上文中介绍了手动测试时需要注意的事项。 例如,如果您拒绝网站尝试访问的任何 API 授予相关权限,会发生什么情况?如何将权限呈现给用户? 自动化测试无法判断网站是为了帮助用户信任它,还是相反地鼓励用户不信任它或认为它被隐藏了。

不过,网站通过审核后,就可以自动执行 API 测试,以确认新版浏览器版本(或即将发布的“Beta 版”和“预览版”中)没有任何损坏情况,并且很大程度上应纳入现有测试套件的一部分。在使用 API Surface 覆盖率时,需要考虑使用自动化测试工具时,大多数浏览器都允许在一定程度上控制哪些 API 和功能可用。Chrome 和 Firefox 都是通过命令行开关运行的。如果在测试工具设置中访问这些选项,您将能在关闭或开启 API 的情况下运行某些测试。(例如,如需了解在启动时添加浏览器标志的方法,请参阅 Cypress 的浏览器启动插件和 puppeteer 的 launch.args 参数)。

仅依靠用户代理字符串获取粗略信息

再举一个例子,从网络问世起,浏览器就随 HTTP User-Agent 标头中的每个请求都发送了自身的说明。几乎在长久以来,人们一直都在呼吁 Web 开发者不要使用用户代理标头的内容为不同的浏览器提供不同的内容,但一直以来,Web 开发者仍然这样做,在某些(但非所有)情况下有一定的正当理由。由于浏览器不希望因网站提供不良体验而挑出一些浏览器,这会导致每个浏览器都伪装成所有其他浏览器,并且用户代理字符串如下所示:

Mozilla/5.0 (Linux; Android 6.0.1; SGP771 Build/32.2.A.0.253; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/52.0.2743.98 Safari/537.36.

其中包括 Mozilla/5.0,这是一款浏览器,20 多年前第一批宇航员登上国际空间站时就发布了该浏览器。用户代理字符串当然是数字“指纹”收集的一种丰富熵来源,为了降低这种指纹识别性,浏览器制造商要么已经冻结了用户代理标头,要么正在努力这样做。这是另一个示例,他们会更改 API 所提供的数据,而无需完全移除 API。发送空白用户代理标头会导致无数个假定存在该标头的网站。因此,浏览器通常会从中移除一些细节,然后在此后大体上保持不变。(您可以在 SafariChromeFirefox 中看到这种情况)。这种防止详细指纹识别的保护实质上意味着,您无法再依赖用户代理标头的准确性;如果您这样做,请务必寻找其他数据源。

需要明确的是,用户代理中的数据不会完全消失,而是以较低的粒度提供,或者有时会不准确,因为系统可能会报告较旧但不变的数字。例如,Firefox、Safari 和 Chrome 会将报告的 macOS 版本号上限设为 10(请参阅关于减少用户代理字符串的更新),了解此处的更多讨论。您可以参阅用户代理缩减,详细了解 Chrome 计划如何减少用户代理字符串中的数据。简而言之,报告的浏览器版本号将仅包含主要版本(因此,即使浏览器是版本 123.10.45.108,版本号也只会变为 123.0.0.0),而操作系统版本将不作任何变化,且选择数量也会很小,并且不作冻结。因此,在虚构的“Windows 20”上运行的虚构 Chrome 版本 123.45.67.89 会将其版本号报告为:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36

您所需的核心信息(浏览器版本)仍然可用:即 Windows 版 Chrome 123。但是,冻结后将不再提供辅助信息(芯片架构、Windows 版本、所模仿的 Safari 版本、浏览器次要版本)。

将其与另一平台上“当前的”Chrome 用户代理进行比较:

Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36,

可以看到,唯一不同的是 Chrome 版本号 (104) 和平台标识符。

同样,Safari 的用户代理字符串会显示平台和 Safari 版本号,还会提供 iOS 上的操作系统版本,但所有其他内容都会被冻结。因此,在假设的 macOS 20 上运行的虚构 Safari 版本 1234.5.67 可能会为其用户代理提供以下形式:

Mozilla/5.0 (Macintosh; **Intel Mac OS X 10_20_0**) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15,

而在虚构的 iOS 20 设备上,则可能是:

Mozilla/5.0 (iPhone; CPU **iPhone OS 20_0** like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/**20.0 Mobile/15E148 Safari/605.1.15**.

同样,核心信息(这是 iOS 或 macOS 上的 Safari)已可供查看,iOS Safari 仍会提供 iOS 版本号;但过去可用的大部分辅助信息已被冻结。重要的是,这包含 Safari 版本号,该版本号不一定可用。

关于对所报告的用户代理所做的更改是热议话题。https://github.com/WICG/ua-client-hints#use-casessummarises 总结了造成这种变化的一些论点和原因,而 Rowan Merewood 提供了幻灯片,其中提供了一些策略,可指导您停止使用用户代理进行区分。

模糊测试

模糊测试是安全实践中的一个术语,是指使用意外的值调用 API,希望 API 能够妥善处理这些意外值并暴露安全问题。Web 开发者应熟悉跨站脚本攻击 (XSS),这涉及到向网页添加恶意脚本,通常是因为网页无法正确转义注入的 HTML(因此您使用文本 <script> 执行搜索查询)。后端开发者会注意到 SQL 注入,如果数据库查询无法正确验证用户输入,就会暴露安全问题(如 xkcd 中的小 Bobby 表特别说明)。模糊测试(也称为“模糊测试”)更适合用于自动尝试向 API 提供许多不同的无效或意外输入,以及检查结果是否存在安全泄露、崩溃或其他不当处理的情况。这些都是故意提供不准确信息的例子。不过,在这种情况下,浏览器会抢占先机(方法是故意使用户代理不正确),以鼓励开发者停止依赖相关数据。

正确做法

  • 检查您的代码库是否存在对用户代理字符串的依赖(搜索 navigator.userAgent 很可能会在您的客户端代码中找到大多数出现的情况,您的后端代码可能会将 User-Agent 作为标头),包括您的依赖项。
  • 如果您在自己的代码中发现了用途,请确定代码要检查什么,并找到另一种实现差异化的方法(或者找到替代依赖项,或者通过提交问题或检查依赖项是否存在更新,在上游处理依赖项)。有时,为了解决 bug,必须进行浏览器区分,但用户代理冻结后,会越来越无法做到这一点。
  • 您可能很安全。如果您只使用品牌、主要版本和平台的核心值,那么这些值几乎肯定仍然可用,并且能在用户代理字符串中正确显示。
  • MDN 介绍了避免依赖于用户代理字符串(“浏览器嗅探”)(其中主要之一是功能检测)的好方法。
  • 如果您在某种程度上依赖于用户代理字符串(即使使用了一些仍然有用的核心值),最好使用即将在新浏览器版本中推出的用户代理进行测试。您可以通过 Beta 版或技术预览 build 自行对这些即将推出的浏览器版本进行测试,但也可以设置自定义用户代理字符串进行测试。进行本地开发时,您可以替换 Chrome、EdgeFirefoxSafari 中的用户代理字符串,以检查您的代码如何处理您可能会从用户那里收到的不同用户代理值。

客户端提示

提供此信息的一个主要建议是用户代理客户端提示,不过并非所有浏览器都支持此功能。支持浏览器将传递三个标头:Sec-CH-UA(提供浏览器品牌和版本号);Sec-CH-UA-Mobile(指示请求是否来自移动设备)和 Sec-CH-UA-Platform(指定操作系统的名称)。(解析这些标头比看起来容易,因为它们是结构化标头而非简单的字符串,这是由浏览器发送“棘手”值的浏览器所强制执行的,如果解析不正确,则将无法正确处理此类标头。与之前一样,这是浏览器提前完成“模糊测试”的示例。使用这些数据的开发者需要妥善处理这些数据,因为数据的设计会导致不当或延迟解析可能会产生不良结果,例如显示不存在的品牌或未正确结束的字符串。)幸运的是,浏览器也会将这些数据作为 navigator.userAgentData 直接提供给 JavaScript,在支持的浏览器中,该数据可能类似于以下对象:

{
  "brands": [
    {
    "brand": " Not A;Brand",
    "version": "99"
    },
    {
    "brand": "Chromium",
    "version": "96"
    },
    {
    "brand": "Google Chrome",
    "version": "96"
    }
  ],
  "mobile": false
}