基于 CSS 的指纹识别

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 $200 免费信用额度!

指纹识别很糟糕。 该术语指的是收集足够多的关于用户的元数据,以便您基本上可以确定他们的身份。 JavaScript 可以访问各种指纹识别可能性,然后结合服务器可以访问的 IP 地址,这意味着指纹识别非常普遍。

您通常不会认为 CSS 是一种指纹识别向量,因此在某种程度上是“安全的”。 但是 Oliver Brotchie 记录了一个想法,它允许在仅使用 CSS 的情况下进行一定程度的 指纹识别。

想想我们拥有的所有 @media 查询。 我们可以使用 any-pointer 测试指针类型。 想象一下,对于每个值,我们都从服务器请求一个完全唯一的 background-image。 如果请求了该图像,我们就知道这些 @media 查询为真。 我们可以使用类似这样的东西开始指纹识别

.pointer {
  background-image: url('/unique-id/pointer=none')
}

@media (any-pointer: coarse) {
  .pointer {
    background-image: url('/unique-id/pointer=coarse')
  }
}

@media (any-pointer: fine) {
  .pointer {
    background-image: url('/unique-id/pointer=fine')
  }
}

结合我们可以使用 prefers-color-scheme 测试深色模式偏好的事实,指纹变得更加清晰。 事实上,它是 CSS 的当前草案 用户首选媒体查询,Oliver 最担心的是这一点

即将发布的草案不仅会使这种方法可扩展,而且还会提高其精度。 目前,如果没有替代方法,很难将每个请求明确地链接到特定访问者,因为唯一可行的方法是通过连接的 IP 地址对请求进行分组。 但是,有了新的草案,通过为每个访问者生成一个随机字符串并将其插入 URL 标签中,我们可以准确地识别来自该访问者的所有请求。

还有更多。 我们可以创建相隔 1px 的媒体查询,并为每个查询请求背景图像,完美地猜测访问者的窗口大小。 可能有十几个或更多很少使用的奇特媒体查询,但它们对使用 CSS 进行指纹识别特别有用。 将其与用于各种事物的 @supports 查询结合起来,基本上可以猜测确切的浏览器。 再将其与测试特定本地字体安装的经典技术结合起来,您就拥有了一台相当不错的指纹识别机器。

@font-face {
  font-family: 'some-font';
  src: local(some font), url('/unique-id/some-font');
}

.some-font {
  font-family:'some-font';
}

生成的用于执行此操作的 CSS 非常庞大 (这是生成它的 Sass),但显然一旦我们可以在 URL 中使用自定义属性,它就会大大减少。

我不太担心这个问题,主要是因为我没有禁用 JavaScript,而 JavaScript 已经能够进行更广泛的指纹识别。 此外,已经存在其他类型的 CSS 安全漏洞,从读取已访问的链接(浏览器已解决)、键盘记录和用户生成的内联样式等,这些漏洞已被其他人指出 关于该主题的另一篇文章中。

但 Oliver 关于指纹识别的研究非常好,值得所有比我更了解网络安全的人一看。