Cross-Browser-Tracking-Summary-Part-3
字数 1682 2025-08-27 12:33:54
WebGL指纹识别与语言检测技术详解
一、WebGL指纹识别技术
1. 核心原理
WebGL指纹识别利用不同设备GPU渲染结果的微小差异作为设备标识。关键技术点包括:
- 渲染差异:不同GPU硬件、驱动版本对同一WebGL指令会产生略微不同的渲染结果
- 数据采集:通过
readPixels方法获取渲染后的像素数据 - 哈希处理:将像素数据转换为唯一哈希值作为指纹
2. 关键代码实现
this.getData = function(gl, id) {
if (!this.finalized) {
throw "Still generating ID's";
return -1;
}
var WebGL = true;
var pixels = new Uint8Array(256 * 256 * 4);
gl.readPixels(0, 0, 256, 256, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
var ven, ren;
var debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
if (debugInfo) {
ven = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);
ren = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
} else {
console.log("debugInfo is not accessable");
ven = 'No debug Info';
ren = 'No debug Info';
}
var hash = pixels.hashCode();
this.toServer(WebGL, ven, ren, hash, id, pixels);
if (sumRGB(pixels) > 1.0) {
return hashRGB(pixels);
} else {
return 0;
}
};
3. 技术要点解析
-
readPixels参数详解:
gl.readPixels(x, y, width, height, format, type, pixels);- 前4个参数:
(0, 0, 256, 256)表示从画布左上角开始读取256x256像素区域 - 第5参数:
gl.RGBA表示读取RGBA四通道数据 - 第6-7参数:
gl.UNSIGNED_BYTE和pixels表示将数据读取到无符号字节数组中
- 前4个参数:
-
像素数据结构:
- 单个像素返回格式:
[Red, Green, Blue, Alpha],例如[0, 0, 0, 255] - 256x256图像数据存储在
256*256*4=262144长度的Uint8Array中
- 单个像素返回格式:
-
GPU信息获取:
var debugInfo = gl.getExtension('WEBGL_debug_renderer_info'); if (debugInfo) { ven = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL); ren = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL); }- 获取GPU厂商和渲染器信息作为辅助识别数据
4. 实际测试结果
- 不同设备、相同浏览器:渲染hash值不同
- 相同设备、不同浏览器:渲染hash值大部分一致
- 结论:GPU渲染差异可作为跨浏览器设备指纹特征
二、语言/文字系统检测技术
1. 核心原理
通过检测浏览器对不同文字系统的渲染支持情况,识别用户环境特征:
- 利用DOM元素测量不同字符的渲染尺寸
- 比较实际渲染尺寸与预期尺寸的差异
- 判断浏览器对特定文字系统的支持情况
2. 代码实现(CoffeeScript)
class LanguageDetector
constructor: ->
@names = safeParseJSON '[ "Latin", "Chinese", ... ]'
@codes = safeParseJSON "[[76,97,116,105,110], [27721,23383], ... ]"
@fontSize = 9
@fontFace = "Verdana"
@extraHeigth = 15
@results = []
3. 实现步骤详解
-
基础定义:
- 定义36种语言/文字系统名称(如Latin、Chinese等)
- 定义各文字系统的Unicode测试字符
- 设置统一的字体和大小(Verdana, 9pt)
-
长宽识别:
@div = document.createElement "div" @test_div.appendChild @div @div.innerHTML = "<font face = '#{@fontFace}' size = " + @fontSize + ">&#" + c + "</font>" @height.push document.getElementById(round).clientHeight @width.push document.getElementById(round).clientWidth- 为每个测试字符创建div元素
- 测量并记录每个字符的渲染高度和宽度
-
长宽校验:
@sh = @heights.pop()[0] # 获取无法渲染字符的基准尺寸 for height in @heights @passed = 0 for h in height if h != @sh @support.push true @passed = 1 break if @passed == 0 @support.push false- 使用无法渲染的字符作为基准(@codes数组第37项)
- 比较各字符尺寸与基准尺寸的差异
- 尺寸不同⇒支持该文字系统;相同⇒不支持
-
统计结果:
@res = [] for s,i in @support if s == true @res.push @names[i]- 收集所有被支持的文字系统名称
4. 技术要点解析
-
基准字符选择:
- 使用无法渲染的字符(如U+1B83)作为基准
- 避免直接使用方块字符,因为不同浏览器可能渲染为不同形状
-
测量原理:
- 支持的字符:实际渲染尺寸 ≠ 基准尺寸
- 不支持的字符:浏览器可能显示为方块或问号,尺寸与基准相同
-
多字符测试:
- 每个文字系统测试多个字符,提高准确性
- 只要有一个字符被正确渲染,即判定支持该文字系统
5. 实际测试结果
不同浏览器支持的文字系统存在差异:
- Chrome:支持30种
- Safari:支持36种
- 差异原因:不同浏览器对罕见文字系统的渲染支持不同
三、应用与防御
1. 实际应用场景
-
设备指纹:
- WebGL指纹 + 语言支持特征 → 高精度设备识别
- 跨浏览器追踪同一设备
-
用户画像:
- 语言支持特征可推测用户区域/语言偏好
- 结合其他指纹增强用户画像精度
-
反欺诈:
- 检测虚拟机/异常环境
- 识别自动化工具
2. 防御措施
-
WebGL指纹防御:
- 禁用WebGL
- 使用Canvas Blocker等插件干扰渲染结果
- 浏览器隐私模式可能限制信息获取
-
语言检测防御:
- 统一所有字符的渲染尺寸
- 干扰DOM元素尺寸测量
- 禁用罕见文字系统的字体
-
综合防御:
- 使用Tor浏览器等隐私保护浏览器
- 定期清理浏览器指纹特征
- 使用虚拟机/容器隔离不同身份
四、总结
本文详细解析了两种重要的浏览器指纹技术:
-
WebGL指纹:
- 利用GPU渲染差异生成设备唯一标识
- 高稳定性,跨浏览器有效
- 实现涉及WebGL渲染和像素数据采集
-
语言/文字系统检测:
- 基于字体渲染支持情况的被动检测
- 可识别浏览器/系统区域设置
- 实现依赖DOM测量和Unicode知识
这两种技术结合其他指纹方法,可构建高精度的用户追踪系统。理解其原理有助于开发隐私保护策略,平衡功能与隐私的需求。