从前端视角看浏览器隐身模式工作原理(1)

8ff42fb1b66087af4e42affd98adb72d.png

nothingprivate1

当我使用无痕模式再次打开这个网站时,浏览器又携带了相同的finger字段去服务器查询相关信息,于是,我被识别出来了

7b110e67c49b68ff1f9c8821c9812a12.png

nothingprivate2

综上:浏览器无痕模式并不能保护你的数据信息不被网站的服务器所获取。准确的说,无痕模式就是掩耳盗铃而已。有兴趣的话,您不妨亲自去Nothing Private[3]体验一下,关于它的原理,后续章节会继续介绍。

隐私模式不能干什么

  • 它不会保护你免受病毒或恶意软件的侵害;

  • 它不会让你的 Internet 服务提供商 (ISP) 无法看到你上网的位置(事实上,无论你做什么,你的 ISP 几乎都可以访问你的所有浏览活动);

  • 它不会阻止网站查看你的实际位置;

  • 当你关闭网页时,你在隐私浏览或隐身模式下保存的任何书签都不会消失,它会被添加到你的正常浏览网页的书签中;

  • 关闭窗口时不会删除你在私密浏览时下载到计算机的文件。

隐私模式使用现状

2017 年,DuckDuckGo[4]对 5,710 名美国人进行了浏览器隐私模式调查,以了解人们对隐私模式的认识以及他们如何使用这一常见的隐私功能,完整报告可参考:A Study on Private Browsing: Consumer Usage, Knowledge, and Thoughts[5]。

简单总结如下:

  • 46% 的美国人使用过隐私浏览;

97973e7a28212a889a416f604b6f221c.png

private-browsing1

  • 人们使用隐私浏览的第一个原因是“令人尴尬的搜索”;

d94c45a26d59977ae85c1ad2a7514de5.png

private-browsing2

  • 76% 使用隐私浏览的美国人无法准确识别其提供的隐私优势;

d2a4424a39429e9a51bc4bf040055ebd.png

private-browsing3

  • 65% 的受访者表示,在了解隐私浏览的局限性后(隐私浏览模式只会阻止你的浏览器历史记录被记录在你的计算机上,并不会提供任何额外的保护),他们感到“惊讶”、“误导”、“困惑”或“受到伤害”;

af6b1d1bcaa69977bbccab0e5847a4b9.png

private-browsing4

  • 84% 的美国人会考虑尝试使用另一个主要的网络浏览器,如果它能提供更多功能来帮助保护他们的隐私的话。

1bcf4a7681817ec5fdbd658f6f0392cf.png

private-browsing5

参考资料:Is Private Browsing Really Private?[6]

从技术视角看隐身模式


用户访问网站的过程

一般情况下,用户访问网站的过程如下图所示:

885158238ae8e0e00c6cc62362fef83e.png

browsing_process1

当一位用户浏览网页时,一般会进行以下操作:

  • 打开浏览器,输入网址。这时候浏览器就会默默将此过程保留在历史记录中;

  • 连接请求通过用户家中的网线,层层递进,到达互联网供应商的主干网络,再接着连接到用户请求的网站地址,这个时候就网站就能拿到用户的 IP 地址了;

  • 网站返回数据给用户,网页大部分的内容作为临时文件被暂存在用户电脑中;

  • 用户如果进行注册/登录,则会将用户信息保存/更新在服务器端。将 Cookie 保留在本地作为验证用户的一种方式,避免用户多次反复的登录。当然进行注册时填写的手机号、邮箱、家庭住址也会被浏览器记录,方便用户下次调用。

可以看到整个过程一般而言有 3 种数据是保存在用户的电脑上的,那就是浏览记录、临时文件与 Cookie 和表单填写的内容。而有 1 或 2 种的数据被保留在了网站那边,就是 IP 地址和用户填写的注册信息。

现在非常多的公司和学校建立了专有的网络环境,对外只显示 1 个 IP,数据返回的时候再发送到相应的内网 IP 上。雇主和学校有心想看的话还是能够知道内网的某个人浏览了什么。对于 HTTP 网站链接,雇主和学校能够完整的了解用户浏览了哪些网站,用户看了哪些内容,停留了多久,针对哪些网站进行了点击跳转等等;对于 HTTPS 网站链接,由于证书的存在和相应的验证机制,一般而言 HTTPS 解密(中间人攻击)很难发动,所以只能够了解到用户浏览了哪些网站而已。同时不恰当的网络环境也会将自己的浏览记录暴露在他人的视野中,比如免费公用的 Wi-Fi。

aee1bff896b2bb6b66964ec2c6b08bb3.png

browsing_process2

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

在 Chrome 76 之前,存在一个漏洞,许多网站利用该漏洞来检测用户是否在 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’)

);

}

后来谷歌修复了一个漏洞,不幸的是,他们的修复导致了另外两种方法,仍然可以用来检测访问者何时进行私密浏览。

  • 基于文件系统大小检测隐身模式:该方法基于为浏览器使用的内部文件系统预留的存储量。安全研究人员 Vikas Mishra发现[7],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’);

}

  • 通过访问时间检测隐身模式:在读取和写入数据时,内存文件系统总是比磁盘文件系统快。在隐身模式下,Chrome 会将写入 API 的数据存储在内存中,而不是像在正常模式下那样将数据持久化到磁盘。这种新的检测方法是由研究员Jesse Li[8] 发现的,它测量对浏览器文件系统的一系列写入。根据这些写入的速度,网站理论上可以确定浏览器是否使用隐身模式。防止这种检测方法的唯一方法是让隐身模式和普通模式使用相同的存储介质,以便 API 无论如何都以相同的速度运行。

49549f254c1083c39e6ccf0413d911c4.png

timings

Chrome 开发人员看到了这两点:在 2018 年 3 月的设计文档中,他们确定了基于时间和文件系统大小检测隐私模式的风险,并进行了替代实现:只将元数据保存在内存中,并加密磁盘上的文件。这将解决网站使用时间来区分内存和磁盘存储的风险,并消除基于文件系统大小和文件系统类型(临时与持久)的差异。

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

如果我们考虑隐身模式的威胁模型,其主要目的是保护同一设备的其他用户的隐私,而不是您访问的网站的隐私,这种权衡可能是不值得的。

隐私模式下如何标识用户

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

我们都知道,浏览器隐身模式可以让别人无法知道你都访问了什么网站和做了什么操作,在隐身模式下,打开的网页和加载的文件不会记录到你的浏览历史记录以及加载历史记录中。在你关闭打开的全部隐身窗口后,系统会删除所有新 Cookie。但是,做为程序猿的我们,如果有类似以下场景:

  • 当产品和数据分析师需要更精准的数据时;

  • 当无需登陆的页面(如社区文章)需要杜绝隐身模式刷 UV 访问量时;

  • 当无需登陆的投票站点需要杜绝隐身模式反复投票点赞时;

  • 当无需登陆的问卷类网站,需要限制用户只能进行一次问卷提交或者第二次打开,需要展示前次提交的结果时;

这对我们来说,无疑是一个巨大的困扰,我们或许都知道设备唯一标识的概念,但在浏览器端,在隐身模式下,在无需用户额外授权时,我们该如何拿到设备唯一标识呢?

在开发场景下,唯一的标识一个设备是一个基本功能,可以拥有很多应用场景,比如软件授权(如何保证你的软件在授权后才能在特定机器上使用)、软件 License,设备标识,设备身份识别等。

如果说要获取设备唯一标识,也许你会想到类似 IMEI、Android ID、MAC 地址等思路,但是Android 10 中官方文档[9] 中有以下两个表述:

  • 从 Android 10 开始,应用必须具有 READ_PRIVILEGED_PHONE_STATE 特许权限才能访问设备的不可重置标识符(包含 IMEI 和序列号)。

  • 默认情况下,在搭载 Android 10 或更高版本的设备上,系统会传输随机分配的 MAC 地址。

一个电脑可能存在多个网卡,多个 MAC 地址,MAC 地址另外一个更加致命的弱点是,MAC 地址很容易手动更改。

至于 Android ID,则不具有真正的唯一性,ROOT、刷机、恢复出厂设置、不同签名的应用等都会导致获取的 Android ID 发生改变,并且不同厂商定制的系统的 BUG 会导致不同的设备可能会产生相同的 Android ID。

其他一些获取设备唯一标识的方法,这篇文章有比较全面的论述:

获取设备唯一标识(Unique Identifier):Windows 系统[10]

广告商是如何追踪我们?日常使用手机该怎样保护隐私[11]这篇文章有一张图则是一个更好的汇总:

8d5859113ee2ba55647fb2ebcb21dfa9.png

identifying

而如果回到我们前端场景下,以上这些方法又多了很多局限性,比如有的需要特许权限,有的需要依赖于原生开发的配合,那么,有没有一种只需要前端参与,也可以获得不错的准确率的唯一标识方案呢? —— 此时就到了浏览器指纹登场的时候了。

FingerPrint 即我们常说的指纹识别,使用手指和拇指前端的纹理按下的纹印来鉴定身份。指纹是鉴别身份的一种可靠的方法,具有唯一性,因为每个人的每个指头上的纹理排列各不相同而且不因发育或年龄而改变。而浏览器指纹是指仅通过浏览器的各种信息,如 CPU 核心数、显卡信息、系统字体、屏幕分辨率、浏览器插件等组合成的一个字符串,就能近乎绝对定位一个用户,就算使用浏览器的隐私窗口模式,也无法避免

这是一个被动的识别方式。也就是说,理论上你访问了某一个网站,那么这个网站就能识别到你,虽然不知道你是谁,但你有一个唯一的指纹,将来无论是广告投放、精准推送、安全防范,还是其他一些关于隐私的事情,都非常方便。

浏览器指纹的技术点与分类
  • 基本指纹:浏览器基本指纹是任何浏览器都具有的特征标识,比如 UserAgent、屏幕分辨率、CPU 核心数、内存大小、浏览器插件及扩展、浏览器设置、语言、硬件类型、操作系统、时区、地理位置、DNS、SSL 证书等众多信息,这些指纹信息“类似”人类的身高、年龄等,有很大的冲突概率,只能作为辅助识别。可以在这个网址[12]进行查看本地浏览器的基本特征。

  • 高级指纹:浏览器高级指纹与基本指纹的区别是:基本指纹就像是人的外貌特征,外貌可以用男女、身高、体重区分,然而这些特征不能对某个人进行唯一性标识,仅使用基本指纹也无法对客户端进行唯一性判定,基于 HTML5 的诸多高级功能就能生成高级指纹了。高级指纹包括 Canvas 指纹、Webgl 指纹、AudioContext 指纹、WebRTC 指纹、字体指纹等;

  • 综合指纹:零散的指纹信息并不能真正的定位到唯一用户,并不能用来代表一个用户的唯一身份(用户指纹)。综合指纹是指将所有的用户浏览器信息组合起来,就可以近乎 99%以上的准确率定位标识用户。将基本指纹和高级指纹组合起来就可以生成综合指纹(用户指纹),这样就可以达到接近 99%以上定位唯一用户了。

更多关于高级指纹的细节和原理,可以通过探讨浏览器指纹[13]这篇文章进行了解。

BrowserLeaks

长期以来,人们一直认为 IP 地址和 Cookie 是用于在线跟踪人员的唯一可靠数字指纹。但过了一段时间,当现代网络技术允许感兴趣的组织在他们不知情且无法避免的情况下使用新方法来识别和跟踪用户时,事情就失控了。

BrowserLeaks[14]就是关于浏览隐私和网络浏览器指纹的。在这里,你将找到一个 Web 技术安全测试工具库,这些工具将向你展示哪些类型的个人身份数据可能会被泄露,以及如何保护自己免受此类泄露。这个网站提供了包括 IP 地址、地理位置、Canvas、WebGL、WebRTC、字体等多种类型指纹的查看及其基本原理概述。

fd7ed5b4590c37058ec82e24fe51ddf2.png

fingerPrint

如果你对其中的技术原理很感兴趣,可以进入BrowserLeaks[15],点击对应卡片标题进行查看和了解,比如 HTML5 Canvas Fingerprinting[16]页面,会给出你的 Canvas 指纹及其唯一性率等信息。

ea0aa0439290487db709a8061d38ea8e.png

fingerPrintCanvas

Nothing Private 的识别原理

前面的章节「浏览器隐身模式真的可以隐身吗?」中介绍了Nothing Private[17]这个站点的测试结果,我们也看到,在提交信息和校验的时候,请求会携带一个finger字段,这个字段就可以被认为是“浏览器指纹”。

查看 GitHub 上Nothing Private 的源码[18]可以发现,Nothing Private 实现“浏览器指纹”的核心逻辑如下:

097ea680931cb4db7895b819064018f1.png

fingerprint1

显而易见,Nothing Private 使用 ClientJS[19](用纯 JavaScript 编写的设备信息和数字指纹)的浏览器指纹识别功能来获取你的 Web 浏览器的指纹,核心方法在于getFingerprint。当你提交表单时,此指纹与你填写的标识一起保存在使用 PHP 作为后端的 MySQL 数据库中。下次你访问该网站时,你的浏览器指纹将与数据库中的列匹配,并返回你填写的标识。

ClientJS 当前用于生成指纹的数据点包括:

user agent, screen print, color depth, current resolution, available resolution, device XDPI, device YDPI, plugin list,

font list, local storage, session storage, timezone, language, system language, cookies, canvas print

我们还是浏览一下 ClientJS 的`getFingerprint`基本逻辑[20]:

78ecd9529f603ccefc5a38b90ed4399b.png

fingerprint2

我们发现,getFingerprint会获取 UA、cookie、本地存储、canvas 指纹等信息,再经过Murmur Hash 算法加密,最终返回一个可以唯一标识浏览器设备的“浏览器指纹”。

MurmurHash 是一种非加密型哈希函数,适用于一般的哈希检索操作。 由 Austin Appleby 在 2008 年发明, 并出现了多个变种,都已经发布到了公有领域(public domain)。与其它流行的哈希函数相比,对于规律性较强的 key,MurmurHash 的随机分布特征表现更良好。

ClientJS 官网地址[21]

FingerprintJS

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

FingerprintJS 的使用也比较简单:

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);

})();

更多关于 fingerprintJS 的信息,可以参考:

  • fingerprintJS 介绍与使用[22]

  • fingerprintJS - GitHub[23]

  • fingerprintJS - 官方文档[24]

上面这些方法,能获得九成以上意义的唯一浏览器指纹,也许并不能完全真的唯一,因为比如重写相关 canvas 方法、使用类似猫头鹰浏览器[25]等特殊浏览器还是会使得相关方法失效,但是技术手段更多时候只是一个通用意义上的解决方案,增加破解的壁垒和成本,我认为支持常用场景下的开发是足够的了。

有了唯一的浏览器指纹,我们就可以在类似统计 UV、点赞、投票的时候,带上相关指纹,自然就可以在极大程度上辨别用户是否存在刷票、刷访问量的行为了,不过,浏览器指纹技术终归是把双刃剑,在解决以上问题的同时,难免会给用户带来更多的信息泄漏困扰。

实现 Canvas Fingerprinting

**Canvas Fingerprinting(Canvas 指纹)基于 Canvas 绘制特定内容的图片,使用 canvas.toDataURL()方法返回该图片内容的 base64 编码字符串。对于 PNG 文件格式,以块(chunk)划分,最后一块是一段 32 位的 CRC 校验,提取这段 CRC 校验码便可以用于用户的唯一标识。**Canvas 利用 HTML5 canvas API 和 JavaScript 来动态生成你想要的图像。和其它跟踪技术一样,这种方法已被成千上万的网站采用了,包括我们熟知的广告领域。

下面是 Canvas 指纹的一个简单实现,原理其实比较简单,不理解的地方可以参考注释:

// PHP 中,bin2hex() 函数把 ASCII 字符的字符串转换为十六进制值。字符串可通过使用 pack() 函数再转换回去

// 下面是PHP 的 bin2hex 的 JavaScript 实现

function bin2hex(s) {

let n,

o = ‘’;

s += ‘’;

for (let i = 0, l = s.length; i < l; i++) {

n = s.charCodeAt(i).toString(16);

o += n.length < 2 ? ‘0’ + n : n;

}

return o;

}

// 获取指纹UUID

function getUUID(domain) {

// 创建  元素

let canvas = document.createElement(‘canvas’);

// getContext() 方法可返回一个对象,该对象提供了用于在画布上绘图的方法和属性

let ctx = canvas.getContext(‘2d’);

// 设置在绘制文本时使用的当前文本基线
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)


核心竞争力,怎么才能提高呢?

成年人想要改变生活,逆转状态?那就开始学习吧~

万事开头难,但是程序员这一条路坚持几年后发展空间还是非常大的,一切重在坚持。

为了帮助大家更好更高效的准备面试,特别整理了《前端工程师面试手册》电子稿文件。

前端面试题汇总

JavaScript

性能

linux

前端资料汇总

完整版PDF资料免费分享,只需你点赞支持,动动手指点击此处就可免费领取了

前端工程师岗位缺口一直很大,符合岗位要求的人越来越少,所以学习前端的小伙伴要注意了,一定要把技能学到扎实,做有含金量的项目,这样在找工作的时候无论遇到什么情况,问题都不会大。

前端面试题汇总

JavaScript

性能

linux

前端资料汇总

完整版PDF资料免费分享,只需你点赞支持,动动手指点击此处就可免费领取了

前端工程师岗位缺口一直很大,符合岗位要求的人越来越少,所以学习前端的小伙伴要注意了,一定要把技能学到扎实,做有含金量的项目,这样在找工作的时候无论遇到什么情况,问题都不会大。

  • 19
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值