WebGL指纹概述
当在浏览器打开的网页上浏览内容时,看到的大多是平面的、静态的图像和文字。但是有时想要在网页上看到更加生动、立体的图像,如3D游戏、虚拟现实应用等。这时,就需要用到WebGL。
简单来说,WebGL(Web Graphics Library)是一种在网页浏览器中运行的技术,它可以用计算机程序在网页上展示出立体的、动态的图像。它基于OpenGL(一种专门用于处理图形的开放标准)。使用WebGL可以在网页上创建各种各样的3D场景和动画。例如可以在网页上看到一个旋转的立方体,或者一个飞行的飞机,甚至是一个完整的3D游戏世界,这些都是通过编写一些特殊的程序代码来实现的,这些代码会告诉浏览器如何绘制这些图像,并且如何根据用户的操作来进行交互。WebGL的一个很大的优势是,它可以在几乎所有现代网页浏览器上运行,而且不需要用户安装任何额外的插件或软件。这意味着,无论是用计算机、平板电脑还是手机,只要有一个支持WebGL的浏览器,就可以享受到生动的3D图像。
浏览器中的WebGL指纹是一种用于识别和跟踪用户的浏览器的技术。它是通过获取浏览器在使用WebGL时的硬件和软件配置信息,如显卡型号、驱动版本、操作系统等,然后通过这些信息生成一个唯一的标识符来实现的。由于每台计算机的硬件和软件配置都不相同,因此生成的WebGL指纹也是唯一的,可以用来识别用户的设备。
图4-5是本机在browserleaks网站查看的WebGL指纹信息,可以看出该指纹信息搜集的是WebGL上下文和显卡相关信息。因此,如果想修改WebGL指纹,只需要对这类硬件信息进行修改即可。
WebGL指纹获取
本节会编写一个JavaScript指纹检测脚本,用来获取WebGL相关信息,由此得出浏览器的WebGL指纹。通过明晰指纹获取的流程,可以更容易地找到指纹的修改点。以下是获取浏览器WebGL指纹信息的JavaScript代码:
function getUnmaskedInfo() {var canvas = document.createElement('canvas');var gl;// 获取WebGL上下文 try {gl = canvas.getContext('webgl') ||canvas.getContext('experimental-webgl');} catch (e) {return "WebGL not supported or disabled";}if (!gl) {return "WebGL not supported or disabled";}var unmaskedVendor = "";var unmaskedRenderer = "";var extensions = gl.getSupportedExtensions();if (extensions.indexOf('WEBGL_debug_renderer_info') !== -1) {var debugInfo = gl.getExtension('WEBGL_debug_renderer_info');unmaskedVendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);unmaskedRenderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);} else {return "WEBGL_debug_renderer_info extension not supported";}var info = {"Unmasked Vendor": unmaskedVendor,"Unmasked Renderer": unmaskedRenderer};info.vendor = gl.getParameter(gl.VENDOR);info.renderer = gl.getParameter(gl.RENDERER);info.version = gl.getParameter(gl.VERSION);info.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);info.maxRenderBufferSize = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE);info.maxViewportDims = gl.getParameter(gl.MAX_VIEWPORT_DIMS);info.extensions = gl.getSupportedExtensions();return info;
}
// 调用函数并输出结果
var unmaskedInfo = getUnmaskedInfo();
console.log(unmaskedInfo);
将上述代码运行在浏览器之中,即可打印出WebGL相关信息。WebGL指纹是通过搜集如图4-6所示的信息,经过特殊编码后生成哈希值,从而得到用户的浏览器指纹信息的。
这段代码是用来获取用户浏览器中WebGL相关信息的函数。在这段代码中,getUnmaskedInfo首先创建一个canvas元素,然后尝试获取WebGL上下文。如果获取成功,则尝试获取更多的WebGL相关信息,如厂商、渲染器、版本等,并返回一个包含这些信息的对象。如果获取不成功,则返回相应的错误信息。最后,通过调用getUnmaskedInfo来获取浏览器中的WebGL信息,并将其打印到控制台中。
利用这些WebGL信息,就可以生成任意编码的值作为指纹信息,传递给网站服务端进行判别。
WebGL指纹修改
由于WebGL相关信息众多,要想成功修改WebGL指纹,需要对要进行指纹修改的网站进行具体分析,了解其搜集的指纹信息进行对症下药,才能顺利完成指纹修改。本节将带领读者修改WebGL中的Debug Renderer info信息,代码如下:
unmaskedVendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);unmaskedRenderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
gl.getParamete是WebGL API中的一个函数,用于获取特定参数的当前值。它接受一个参数,该参数指定要查询的信息类型,并返回相应的值。UNMASKED_VENDOR_WEBGL用于获取WebGL渲染上下文的厂商信息,而UNMASKED_RENDERER_WEBGL用于获取渲染器信息。通常情况下,修改这两个值,WebGL相关指纹信息就会发生改变。
关于WebGL指纹信息的代码文件位于“src\third_party\blink\renderer\modules\webgl”当中,其中的webgl_rendering_context_base.cc文件包含了最基础的WebGL渲染信息。
先来修改其中的vendor厂商信息,具体代码如下:
case WebGLDebugRendererInfo::kUnmaskedVendorWebgl:if (ExtensionEnabled(kWebGLDebugRendererInfoName)) {if (IdentifiabilityStudySettings::Get()->ShouldSampleType(blink::IdentifiableSurface::Type::kWebGLParameter)) {RecordIdentifiableGLParameterDigest(pname, IdentifiabilityBenignStringToken(String(ContextGL()->GetString(GL_VENDOR))));}return WebGLAny(script_state,String(ContextGL()->GetString(GL_VENDOR)));}SynthesizeGLError(GL_INVALID_ENUM, "getParameter","invalid parameter name, WEBGL_debug_renderer_info not enabled");return ScriptValue::CreateNull(script_state->GetIsolate());
可以看出,该代码判断到条件语句WebGLDebugRendererInfo::kUnmaskedVendorWebgl的时候,会判别kWebGLDebugRendererInfoName扩展是否已经启用,该拓展可以提供额外的WebGL渲染器信息。
- 启用了扩展:如果启用,代码进一步处理获取显卡供应商的信息,并记录这些信息用于标识能力研究。这个扩展提供了一种方式来获取通常不公开的详细WebGL渲染器信息。
- 未启用拓展:如果扩展没有被启用,代码则会生成一个错误。错误指出无法获取请求的参数,因为相关的调试扩展没有启用。随后,代码返回一个空值作为函数的结果,表明操作未能成功执行。
要修改此处的WebGL厂商信息,可以选择在启用拓展时候修改,如果未启用就正常返回空值。通过传递名为webgl_vendor的命令行参数,即可完成厂商信息的修改。代码如下:
//ruyiconst base::CommandLine* ruyi_command_line =base::CommandLine::ForCurrentProcess();if (ruyi_command_line->HasSwitch(blink::switches::kRuyi)) {const std::string ruyi_fp = ruyi_command_line->GetSwitchValueASCII(blink::switches::kRuyi);absl::optional<base::Value> json_reader =base::JSONReader::Read(ruyi_fp);std::string webgl_vendor =*(json_reader->GetDict().FindString("webgl_vendor"));return WebGLAny(script_state,String(webgl_vendor));}//ruyi end
接着,再来看看显卡信息,代码如下:
case WebGLDebugRendererInfo::kUnmaskedRendererWebgl:if (ExtensionEnabled(kWebGLDebugRendererInfoName)) {if (IdentifiabilityStudySettings::Get()->ShouldSampleType(blink::IdentifiableSurface::Type::kWebGLParameter)) {RecordIdentifiableGLParameterDigest(pname, IdentifiabilityBenignStringToken(String(ContextGL()->GetString(GL_RENDERER))));}return WebGLAny(script_state,String(ContextGL()->GetString(GL_RENDERER)));}SynthesizeGLError(GL_INVALID_ENUM, "getParameter","invalid parameter name, WEBGL_debug_renderer_info not enabled");return ScriptValue::CreateNull(script_state->GetIsolate());
可以看出结构上是和修改厂商信息没有太大区别的,依然可以在启用拓展的情况下对其中的显卡信息返回值进行定制修改。