PaulChess/MyBlog

从前端视角看浏览器隐身模式下你是如何被追踪的

Opened this issue · 0 comments

本issue仅仅是学习时的记录:
原文章链接如下: https://juejin.cn/post/6994228279909548062

image

1. 隐私模式隐藏了什么

  隐私浏览旨在避免在计算机上保留浏览会话的痕迹,主浏览窗口中的cookie、历史记录不会被保留,关闭隐私窗口时,历史记录、保存的密码以及在文本框中键入的内容都会被擦除。

  隐私浏览可以保护你的隐私免受使用你计算机的其他人的侵害,并减少你在访问网站时透露的个人信息。但是!:隐私浏览不会让你匿名,也不会保护你免受监视和大型技术的窥探

  Chrome不会保存的信息:浏览记录、cookie和网站数据、在表单中填写的信息. 但是一下各方可能可以看到你的活动: 你所访问的网站、你的雇主或所在的学校、你的互联网服务提供商。

  在隐身模式下,网站还是可以通过关联其他信息来发现你是谁,找出你的身份。这些关联信息比如你的IP地址、设备类型和浏览习惯等等.. 这些信息是不会隐藏的,FaceBook和Google等科技公司拥有大量用户的信息,通过连接这些点,就可以识别你的身份。

2. 浏览器隐身模式真的可以隐身吗?

  当然是不能
  可以通过Nothing Private来验证.

  这里会有一个固定的finger字段(应该是根据一些设备信息,ua等等生成的唯一标识),然后携带着你的finger和输入的name调用接口去保存起来. 接着我们进入到无痕模式,进入页面后就会调用一个接口传入finger(与正常页面生成的那个finger一样!!!)与checked: 1就会返回你之前输入的那个name. 牛!

image

image

  综上:无痕模式并不能保护你的数据信息不被网站的服务器所获取!

隐私模式不能干什么

  • 不会保护你免受病毒或恶意软件的侵害;
  • 不会让互联网服务提供商(ISP)无法看到你上网的位置(事实上,无论你做什么,你的ISP几乎可以访问你所有的浏览活动)
  • 不会阻止网站查看你的实时位置 ip?
  • 当你关闭网页时,你在隐私浏览或隐身模式下保存的任何书签都不会消失,它会被添加到你的正常浏览网页的书签中;
  • 关闭窗口时不会删除你在私密浏览时下载到计算机的文件

用户访问网站的过程

image

访问网站过程:

  1. 打开浏览器,输入网址。此时浏览器会将此过程保留在历史记录中;
  2. 连接请求通过网线,层层递进,到达网络提供商(移动、电信...)的主干网络,然后连接到用户访问的网址,此时网站那边就能拿到用户的ip地址了;
  3. 网站返回网页内容,网页里的大部分内容会作为临时文件保存在用户的电脑中;
  4. 用户如果进行了注册/登录,用户信息就会保存/更新在服务端。将cookie保留在本地作为用户凭证。注册时填写的一些邮箱等等信息也会被浏览器所记录。

  综上过程,有三种数据会被保存在用户的电脑上:浏览记录临时文件cookie及表单中填写的内容。有1~2种数据被保留在了网站那边,即:ip地址和用户填写的注册信息。

  公司和学校建立的专有网络环境:对外只展示一个IP, 数据返回的时候再发送到响应的内网IP上,相当于一个单位有一个总的代理人,帮你们统一向外请求,请求回来以后再根据内网的ip返回对应的数据。
  因此,如果雇主和学校有心想看的话是可以知道内网的某个人浏览了什么的。对于HTTP网站链接。雇主和学校可以完整地了解用户浏览了哪些网站,用户看了哪些内容,停留了多久,跳转了哪些网页...... 但是对于HTTPS网站由于证书的存在和相应的验证机制,一般HTTPS解密(中间人攻击)很难发动,因此只能够了解到用户浏览了哪些网站而已
链接不恰当的网络环境也会将自己的浏览记录暴露给他人,比如免费公用的WIFI。

image

浏览器隐身模式检测的博弈

漏洞1检测用户是否是在Chrome的隐身模式下访问网站。这些网站可以尝试使用FileSystem API用于存储临时或永久文件的。这个API在隐身模式下被禁用,但在非隐身模式下存在,可以通过该差异进行检测(该漏洞现已修复):

const fs = window.RequestFileSystem || window.webkitRequestFileSystem;
if (!fs) {
  console.log('check failed?');
} else {
    fs(
    window.TEMPORARY,
    100,
    console.log.bind(console, 'not in incognito mode'),
    console.log.bind(console, 'incognito mode')
  );
}

漏洞2: 基于文件系统大小检测隐身模式。Chrome 隐身模式和非隐身模式之间存储配额存在区别,如果临时存储配额<= 120MB,那么可以肯定地说它是一个隐身窗口,该方法通过navigator.storage.estimateAPI来进行获取和判断(截至现在该漏洞也已修复)。

if ('storage' in navigator && 'estimate' in navigator.storage) {
  const { usage, quota } = await navigator.storage.estimate();
  console.log(`Using ${usage} out of ${quota} bytes.`);

  if (quota < 120000000) {
    console.log('Incognito');
  } else {
    console.log('Not Incognito');
  }
} else {
  console.log('Can not detect');
}

漏洞3: 通过访问时间检测隐身模式: 在读取和写入数据时,内存文件系统总是比磁盘文件系统快。研究员发现,隐身模式下,Chrome写API数据的操作总是要比正常模式下快,所以可以根据写入速度确定浏览器是否使用隐身模式。防止这种检测方法的唯一方式是让隐身模式和普通模式使用同样的存储介质,使得它们的写入速度一样。
Chrome开发人员的解决办法是: 只将元数据存储在内存中,并加密磁盘上的文件,来解决网站使用时间来区分内存和磁盘存储的风险,并消除基于文件系统大小和文件系统类型的差异。

这样的解决方案虽然可以抵御隐私模式检测,但是它会留下元数据:及时数据本身无法解密,它的存在也提供了隐身使用的证据。

隐私模式下如何标识用户

设备唯一标识和浏览器指纹

什么时候我们需要知道用户是在隐私模式下访问的:

  • 产品及数据分析师需要更精确的数据
  • 当无需登录的页面需要杜绝隐身模式刷UV
  • 当无需登录的投票站点杜绝隐身模式刷票
  • 当无需登陆的问卷类网站,需要限制用户只能进行一次问卷提交或者第二次打开,需要展示前次提交的结果时;
    *................

在浏览器的隐身模式下,在无需用户额外授权的情况下,如何拿到用户的设备唯一标识呢?

开发场景下,唯一的标识一个设备是一个基本功能,有很多的应用场景,如软件授权软件License设备标识设备身份识别等。

怎样获取设备唯一标识,可能你会想到IMEIAndroid IDMAC地址,MAC地址,Android ID等都不是唯一的,且可能会被篡改。
下图是ios和android设备上拿到一些独有id的方法:
image

但是这些方法有的需要特许权限,有的需要原生开发的配合.
是否有只需要前端参与,也可以获得不错的准确率的唯一标识方案呢? -- 浏览器指纹登场。
而浏览器指纹是指仅通过浏览器的各种信息,如 CPU 核心数、显卡信息、系统字体、屏幕分辨率、浏览器插件等组合成的一个字符串,就能近乎绝对定位一个用户,就算使用浏览器的隐私窗口模式,也无法避免。
这是一个被动的识别方式。也就是说,理论上你访问了某一个网站,那么这个网站就能识别到你,虽然不知道你是谁,但你有一个唯一的指纹,将来无论是广告投放、精准推送、安全防范,还是其他一些关于隐私的事情,都非常方便。

浏览器指纹的技术点和分类

  • 基本指纹: 浏览器基本指纹是任何浏览器都具有的特征标识,比如 UserAgent、屏幕分辨率、CPU 核心数、内存大小、浏览器插件及扩展、浏览器设置、语言、硬件类型、操作系统、时区、地理位置、DNS、SSL 证书等众多信息,这些指纹信息“类似”人类的身高、年龄等,有很大的冲突概率,只能作为辅助识别。可以在这个网址进行查看本地浏览器的基本特征。
  • 高级指纹: 浏览器高级指纹与基本指纹的区别是:基本指纹就像是人的外貌特征,外貌可以用男女、身高、体重区分,然而这些特征不能对某个人进行唯一性标识,仅使用基本指纹也无法对客户端进行唯一性判定,基于 HTML5 的诸多高级功能就能生成高级指纹了。高级指纹包括 Canvas 指纹、Webgl 指纹、AudioContext 指纹、WebRTC 指纹、字体指纹等;
  • 综合指纹:零散的指纹信息并不能真正的定位到唯一用户,并不能用来代表一个用户的唯一身份(用户指纹)。综合指纹是指将所有的用户浏览器信息组合起来,就可以近乎 99%以上的准确率定位标识用户。将基本指纹和高级指纹组合起来就可以生成综合指纹(用户指纹),这样就可以达到接近 99%以上定位唯一用户了。

Nothing Private 的识别原理

image

clienJS库 github地址: https://github.com/jackspirou/clientjs
FingerprinJS库: 是一个快速的浏览器指纹库,纯 JavaScript 实现,没有任何依赖。。默认情况下,使用 Murmur Hash 算法返回一个 32 位整数,Hash 函数可以很容易地更换。同时,他也很轻量:开启 gzipped 后只有 843 bytes,匿名识别网络浏览器的准确率高达 94%。

import FingerprintJS from '@fingerprintjs/fingerprintjs';

// 应用启动时初始化:Initialize an agent at application startup.
const fpPromise = FingerprintJS.load();
(async () => {
  // Get the visitor identifier when you need it.
  const fp = await fpPromise;
  const result = await fp.get();

  // This is the visitor identifier:
  const visitorId = result.visitorId;
  console.log(visitorId);
})();