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());
可以看出結構上是和修改廠商信息沒有太大區別的,依然可以在啟用拓展的情況下對其中的顯卡信息返回值進行定制修改。