01 开源实践
参与贡献的六个开源项目
团队曾为以下六个国际开源项目贡献代码。它们研究的问题各有侧重,从网页如何采集一项特征,到这一特征在大量浏览器样本中有多常见。
- 浏览器可识别性与跟踪防护
Panopticlick / Cover Your Tracks
EFF 的公开测试将浏览器配置放入已有样本中比较,衡量其可区分程度,并检查浏览器对网页追踪的防护表现。
- 客户端特征采集
FingerprintJS
在浏览器内采集多项特征并计算标识。各个组件的原始结果可单独查看,便于找出是哪一项读数引起了标识变化。
- 浏览器接口防护
CanvasBlocker
Firefox 扩展,控制网页对可用于识别浏览器的接口的访问,涉及 Canvas、音频和元素几何等数据。
- 指纹样本与时间序列
AmIUnique
研究浏览器在人群样本中的独特程度,也观察同一浏览器的指纹如何随时间变化。两类样本分别用于考察可区分性与稳定性。
- 自动化网页隐私测量
OpenWPM
通过自动化浏览器访问站点,在一次访问中记录 HTTP 流量、Cookie 和 JavaScript 调用,用于分析真实网页上的追踪行为。
- 跨接口一致性分析
fpscanner
交叉检查浏览器提供的多组信号,从属性之间的矛盾查找异常。例如,将所声明的浏览器身份与脚本可见的运行环境对照。
02 实验记录
一张白色画布的三种读法
在 Windows 的 Edge 中载入客户端使用的 Canvas 保护脚本,绘制一张完全不透明的白色画布。固定画布内容,只改变保护开关与环境种子。
逐字节核对
- 直接读回
用
getImageData连读两次完整画布。再从坐标 (8, 4) 读取 10 × 6 像素,与整图中同一区域比较。 - 解码导出图像
分别用
toDataURL和toBlob导出 PNG,解码为 RGBA,与直接读回的像素逐字节比较。
| 样本 | 环境种子 | RGBA 摘要 |
|---|---|---|
| 基准 | 保护关闭 | d0ff1b294b52 |
| 环境 A | 1235490086 | 192ec4ec906c |
| 环境 B | 1235490087 | f9bd2544a04a |
三种读法在各自样本内逐字节相同。环境 A 与基准相比,78 个像素各有一个颜色通道从 255 变为 254,所有像素的透明度保持 255。
取样条件与完整摘要
· Windows · Microsoft Edge 133.0.3065.92 · 32 × 16 像素 · RGBA8
- 基准
d0ff1b294b5288d1ae1421eadf5b2d38a8752b76d472ff30bed9028e25b1c5b8- 环境 A
192ec4ec906cf47201ad857bc26a225ec1ab362e4b9625aeca9b432f513f7a0d- 环境 B
f9bd2544a04ad98a3e5db0cfdce13619b7136f0392f8bc357feb124186471d14
03 技术目录
指纹信号与环境隔离
我们把研究中的 24 个检查项整理为六组。设备身份要跨接口核对,图形与音频需要固定输入,登录状态则要在同一站点的不同环境中复查。
设备身份与执行上下文
- 请求头与 User-Agent
- 电脑端同时核对网络请求和页面脚本读到的浏览器身份。系统名称、移动端标记和版本号应当能相互对应。
- Client Hints
- 分开记录品牌主版本和高熵字段,包括完整版本、体系结构及系统版本。浏览器拒绝提供某项数据时,保留其缺失状态。
- 主线程与 Worker
- 在页面、专用 Worker 和共享 Worker 中读取平台与语言。重建后台线程后再读一次,可定位只在首次初始化时出现的差异。
- 机型与硬件线索
- 对照机型模板、GPU 型号与触控点数。逻辑处理器数量和浏览器报告的内存估计值另列,保留各项读数的来源。
画布与图形栈
- Canvas 2D
- 检测页在 300 × 100 像素画布上绘制文字、色块和叠色圆形,再为 RGBA 字节计算 SHA-256。固定绘图指令后才比较摘要。
- 局部读回与 PNG 导出
- 截取一块已知坐标的矩形,与整图中相同区域逐字节比较。通过 toDataURL 和 toBlob 导出的 PNG 也要解码后再比。
- WebGL 厂商与渲染器
- 分别检查 WebGL 及 WebGL 2 的厂商和渲染器字段。浏览器开放调试扩展时,还可读取未屏蔽的 GPU 标识。
- 图形能力
- 记录 WebGL 版本、最大纹理尺寸与扩展清单。即使两个环境报告相同的显卡名称,这些能力值仍值得单独核对。
屏幕、排版与音频
- 屏幕与视口
- 并列记录屏幕逻辑尺寸、屏幕可用区域、页面视口与设备像素比。缩放页面或调整窗口后,逐项查看哪些数值发生了变化。
- 字体回退
- 对同一串字符,分别以衬线、无衬线和等宽字体测量基准字宽。换入候选字体后,用宽度差异判断它是否可能可用。
- 元素边界框
- 对轻微旋转的文本读取 getBoundingClientRect()。位置和宽高分别比较,以区分坐标微调与实际排版尺寸变化。
- Web Audio
- 检测页以 44.1 kHz 离线渲染,截取 500 个样本计算摘要。客户端的音频防护针对分析器快照,保留播放和编辑所用的原始 PCM 缓冲。
网络出口与地区
- 代理出口
- 为环境分别配置 HTTP、HTTPS 或 SOCKS5 代理。重启环境后,用检测服务实际收到的出口 IP 核对代理线路。
- WebRTC 与 ICE
- HTTP 请求和实时连接分别取样。配置 STUN 服务后可主动收集 ICE 候选地址,需保留网页通话的环境可单独设置 WebRTC。
- 语言与时区
- 对读首选语言、语言列表、IANA 时区和指定日期的 UTC 偏移。再核对 Worker 里的读数,检查地区预设是否贯穿两个上下文。
- 定位与精度
- IP 归属地来自网络出口查询。定位接口在授权后返回经纬度和精度半径,两组数据分别记录,便于查明地区差异来自哪里。
设备接口与站点权限
- 媒体设备枚举
- 比较开启或关闭设备隐藏时 enumerateDevices() 的返回列表。在启用隐藏的环境中,页面读到空列表。
- 语音合成
- 系统安装的语音包会影响 getVoices() 的结果。环境可按语言和名称整理语音列表,限制返回条目,再检查多次读取的顺序。
- 权限状态
- 分别查询定位、通知、摄像头和麦克风的权限,区分已允许、已拒绝和尚待询问。读取授权状态与实际调用设备分开进行。
- 隐私偏好
- 记录 Do Not Track、Global Privacy Control 和安全上下文。对照浏览器显式返回的值与未提供的字段,保留两种状态的区别。
会话隔离与协作
- 同源多账号
- 在两个环境中打开同一站点并分别登录。切换、刷新后核对各自的 Cookie 和账号身份,这是检验会话边界的直接方法。
- 站点存储
- 向同一来源写入不同的环境标记。分别复查 localStorage 在重开环境后的取值,以及 sessionStorage 随标签页变化的情况。
- 配置重载
- 保存设备或网络配置后重启目标环境。将启动后的网页读数与保存值逐项比较,定位仍沿用旧配置的环节。
- 团队环境
- 电脑端按项目共享指纹和网络配置。用两个成员账号分别打开同一份配置,检查授权范围,同时核对各自独立的网站登录状态。