WebGL 渲染器字串與硬體訊號:你的 GPU 透露了多少關於你的事

瀏覽器所在的硬體,會以數種細微的方式洩漏到頁面中。其中沒有一項能指出機器的名稱,但合在一起,就足以精確描述它,讓它與大多數其他機器區分開來。
渲染器字串
WebGL 提供一個名為 WEBGL_debug_renderer_info 的擴充功能,帶有兩個值:未遮蔽的廠商與未遮蔽的渲染器。在 Windows 上使用 Chromium 時,渲染器通常會是類似 ANGLE (NVIDIA, NVIDIA GeForce RTX 2060 SUPER (0x00001F06) Direct3D11 vs_5_0 ps_5_0, D3D11) 的內容。這一行就給出了 GPU 廠商、確切型號、PCI 裝置識別碼、圖形 API 與著色器模型,這也強烈暗示了作業系統,因為這種字串只存在於 Windows。
Firefox 和 Safari 在不同時期曾遮蔽或一般化這個字串;Chromium 則直接公開。遮蔽它的瀏覽器會回傳一個通用的值,診斷頁面會顯示「渲染器資訊已遮蔽」,而不是亂猜。
數量與大小
navigator.hardwareConcurrency 回傳邏輯 CPU 執行緒的數量。navigator.deviceMemory 回傳大約的 RAM 容量,會被四捨五入為一小組固定值,在 Chromium 中上限為 8,所以擁有 32 GB 的機器也只會回報 8。screen.width 與 screen.height 給出顯示器大小,availWidth 與 availHeight 扣掉工作列,devicePixelRatio 則透露縮放比例。screen.colorDepth 幾乎總是 24。navigator.maxTouchPoints 把觸控裝置和其他裝置區分開來。
其中有些項目看起來很無害,識別力卻異常地高。執行緒數量只有少數幾個常見的值,但它是一家知名商業指紋辨識服務賦予高權重的欄位之一,正因為它既便宜又穩定。螢幕大小結合像素比與可用高度,比 User-Agent 更能縮小機器的範圍。
媒體裝置
navigator.mediaDevices.enumerateDevices() 回傳系統擁有的攝影機、麥克風與喇叭。在沒有權限的情況下,現代瀏覽器只回傳種類與數量,標籤則是空的,所以頁面只知道「一支攝影機、一支麥克風、一個輸出裝置」,其他一無所知。只要對任何網站授予存取權,標籤就會顯露出來。只顯示數量的診斷頁面,行為就如同一個沒有權限的頁面。
再談一致性
硬體訊號是偽造最容易出錯的地方。一個宣稱是 MacBook、卻帶有 NVIDIA Direct3D 渲染器、24 個執行緒與 1366×768 螢幕的設定檔,描述的是一台不存在的機器。網站不需要資料庫就能察覺這一點,幾條規則就能抓到。如果設定檔更改了其中任何一個值,就必須把全部改成真實裝置確實出貨過的組合,並在多次造訪之間維持不變。
該檢查什麼
讀取渲染器字串,問問它是否與 User-Agent 中的作業系統相符。讀取螢幕大小,問問它是否與像素比及可用高度相符。讀取執行緒數量與記憶體,問問這組搭配對該 GPU 來說是否合理。診斷頁面把這些資訊並排列出,正是為了這個目的;判斷則由你來做。


