从前端视角看浏览器隐身模式下你是如何被追踪的
认识隐私模式
隐私模式隐藏了什么
浏览器隐身模式真的可以隐身吗?
finger
字段。finger
字段去服务器查询相关信息,于是,我被识别出来了。隐私模式不能干什么
它不会保护你免受病毒或恶意软件的侵害;
它不会让你的 Internet 服务提供商 (ISP) 无法看到你上网的位置(事实上,无论你做什么,你的 ISP 几乎都可以访问你的所有浏览活动);
它不会阻止网站查看你的实际位置;
当你关闭网页时,你在隐私浏览或隐身模式下保存的任何书签都不会消失,它会被添加到你的正常浏览网页的书签中;
关闭窗口时不会删除你在私密浏览时下载到计算机的文件。
46% 的美国人使用过隐私浏览;
人们使用隐私浏览的第一个原因是“令人尴尬的搜索”;
76% 使用隐私浏览的美国人无法准确识别其提供的隐私优势;
65% 的受访者表示,在了解隐私浏览的局限性后(隐私浏览模式只会阻止你的浏览器历史记录被记录在你的计算机上,并不会提供任何额外的保护),他们感到“惊讶”、“误导”、“困惑”或“受到伤害”;
84% 的美国人会考虑尝试使用另一个主要的网络浏览器,如果它能提供更多功能来帮助保护他们的隐私的话。
从技术视角看隐身模式
用户访问网站的过程
打开浏览器,输入网址。这时候浏览器就会默默将此过程保留在历史记录中;
连接请求通过用户家中的网线,层层递进,到达互联网供应商的主干网络,再接着连接到用户请求的网站地址,这个时候就网站就能拿到用户的 IP 地址了;
网站返回数据给用户,网页大部分的内容作为临时文件被暂存在用户电脑中;
用户如果进行注册/登录,则会将用户信息保存/更新在服务器端。将 Cookie 保留在本地作为验证用户的一种方式,避免用户多次反复的登录。当然进行注册时填写的手机号、邮箱、家庭住址也会被浏览器记录,方便用户下次调用。
浏览器隐身模式检测的博弈
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发现,Chrome 隐身模式和非隐身模式之间存储配额存在区别,如果临时存储配额<= 120MB,那么可以肯定地说它是一个隐身窗口。这个方法主要通过
navigator.storage.estimate
API 来进行获取和判断。
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 发现的,它测量对浏览器文件系统的一系列写入。根据这些写入的速度,网站理论上可以确定浏览器是否使用隐身模式。防止这种检测方法的唯一方法是让隐身模式和普通模式使用相同的存储介质,以便 API 无论如何都以相同的速度运行。
隐私模式下如何标识用户
设备唯一标识与浏览器指纹
当产品和数据分析师需要更精准的数据时;
当无需登陆的页面(如社区文章)需要杜绝隐身模式刷 UV 访问量时;
当无需登陆的投票站点需要杜绝隐身模式反复投票点赞时;
当无需登陆的问卷类网站,需要限制用户只能进行一次问卷提交或者第二次打开,需要展示前次提交的结果时;
...
从 Android 10 开始,应用必须具有
READ_PRIVILEGED_PHONE_STATE
特许权限才能访问设备的不可重置标识符(包含 IMEI 和序列号)。默认情况下,在搭载 Android 10 或更高版本的设备上,系统会传输随机分配的 MAC 地址。
浏览器指纹的技术点与分类
基本指纹:浏览器基本指纹是任何浏览器都具有的特征标识,比如 UserAgent、屏幕分辨率、CPU 核心数、内存大小、浏览器插件及扩展、浏览器设置、语言、硬件类型、操作系统、时区、地理位置、DNS、SSL 证书等众多信息,这些指纹信息“类似”人类的身高、年龄等,有很大的冲突概率,只能作为辅助识别。可以在这个网址进行查看本地浏览器的基本特征。
高级指纹:浏览器高级指纹与基本指纹的区别是:基本指纹就像是人的外貌特征,外貌可以用男女、身高、体重区分,然而这些特征不能对某个人进行唯一性标识,仅使用基本指纹也无法对客户端进行唯一性判定,基于 HTML5 的诸多高级功能就能生成高级指纹了。高级指纹包括 Canvas 指纹、Webgl 指纹、AudioContext 指纹、WebRTC 指纹、字体指纹等;
综合指纹:零散的指纹信息并不能真正的定位到唯一用户,并不能用来代表一个用户的唯一身份(用户指纹)。综合指纹是指将所有的用户浏览器信息组合起来,就可以近乎 99%以上的准确率定位标识用户。将基本指纹和高级指纹组合起来就可以生成综合指纹(用户指纹),这样就可以达到接近 99%以上定位唯一用户了。
BrowserLeaks
Nothing Private 的识别原理
finger
字段,这个字段就可以被认为是“浏览器指纹”。getFingerprint
。当你提交表单时,此指纹与你填写的标识一起保存在使用 PHP 作为后端的 MySQL 数据库中。下次你访问该网站时,你的浏览器指纹将与数据库中的列匹配,并返回你填写的标识。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
getFingerprint
基本逻辑:getFingerprint
会获取 UA、cookie、本地存储、canvas 指纹等信息,再经过Murmur Hash
算法加密,最终返回一个可以唯一标识浏览器设备的“浏览器指纹”。MurmurHash 是一种非加密型哈希函数,适用于一般的哈希检索操作。由 Austin Appleby 在 2008 年发明, 并出现了多个变种,都已经发布到了公有领域(public domain)。与其它流行的哈希函数相比,对于规律性较强的 key,MurmurHash 的随机分布特征表现更良好。 ClientJS 官网地址
FingerprintJS
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);
})();
fingerprintJS 介绍与使用
fingerprintJS - GitHub
fingerprintJS - 官方文档
实现 Canvas Fingerprinting
// 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) {
// 创建 <canvas> 元素
let canvas = document.createElement('canvas');
// getContext() 方法可返回一个对象,该对象提供了用于在画布上绘图的方法和属性
let ctx = canvas.getContext('2d');
// 设置在绘制文本时使用的当前文本基线
ctx.textBaseline = 'top';
// 设置文本内容的当前字体属性
ctx.font = "14px 'Arial'";
// 设置用于填充绘画的颜色、渐变或模式
ctx.fillStyle = '#f60';
// 绘制"被填充"的矩形
ctx.fillRect(125, 1, 62, 20);
ctx.fillStyle = '#069';
// 在画布上绘制"被填充的"文本
ctx.fillText(domain, 2, 15);
ctx.fillStyle = 'rgba(102, 204, 0, 0.7)';
ctx.fillText(domain, 4, 17);
// toDataURL返回一个包含图片展示的 data URI
let b64 = canvas.toDataURL().replace('data:image/png;base64,', '');
// atob() 方法用于解码使用 base-64 编码的字符串;base-64 编码使用方法是 btoa(),这俩都是window全局方法
let crc = bin2hex(atob(b64).slice(-16, -12));
return crc;
}
// 调用时,你可以传入任何你想传的字符串,并不局限于传递domain,这里只是为了便于区分站点
console.log(getUUID('https://www.baidu.com/'));
PHP bin2hex() 函数
在图片格式上,不同 web 浏览器使用了不同的图形处理引擎、不同的图片导出选项、不同的默认压缩级别等。
在像素级别来看,操作系统各自使用了不同的设置和算法来进行抗锯齿和子像素渲染操作。
即使是相同的绘图操作,最终产生的图片数据在 hash 层面上依然是不同的。
如何更好的保护个人隐私
我们应该在何时使用私密/隐身模式?
即使你使用的是隐私浏览模式,也并不意味着你可以做一些邪恶的事情; 也许你想将你的工作和个人生活分开; 你可能会共用一台计算机或设备,并且你不希望你的家人、朋友、同事窥探; 你可能正在购买礼物,但你不希望任何东西破坏可能的惊喜; 或者,也许你只是想限制公司收集有关你的数据量,并且你重视隐私; 使用公共场所的电脑设备时。
如何防止被生成“浏览器指纹”?
猫头鹰浏览器是基于 chromium 代码修改编译的浏览器,从底层对各种 API 做了修改,可以交给用户自定义返回各种数据,比如 Canvas、Webgl、AudioContext、WebRTC、字体、UserAgent、屏幕分辨率、CPU 核心数、内存大小、插件信息、语言等信息,这样就可以完全避免被“生成”唯一用户指纹了。因为在线公司、广告商和开发人员喜欢跟踪你的在线活动和操作,以便为你提供有针对性的广告,通常,大家认为这是侵犯用户隐私的。
如何免受广告跟踪器的监视和跟踪
SameSite=None
),可参考下图。而 Chrome 的终极目标,是要在 2022 年完全消灭第三方 Cookie,像 Safari 和 Brave 已经做的那样,SameSite Cookie 就是第一步。友情提示:VPN 是中立性的技术,使用由相关单位构建并且登记备案的 VPN 不属于违法行为,而私自搭建的则属于违法行为(即使用非法 VPN 是违法的);如果只是使用 VPN 连接国际网络进行必要的工作、查阅必要信息,是不属于违法行为的;如果使用 VPN 在国际互联网制作、复制、查阅和传播违法信息的,则需要依法追究违法责任。
参考资料
探讨浏览器指纹
浏览器的隐私模式,真的能完全保护我们的隐私吗?
Google Chrome Incognito Mode Can Still Be Detected by These Methods
Private Browsing Won't Protect You From Everything