Chromium 148 Math.tanh 作業系統指紋辨識漏洞
Chromium 148 Math.tanh 作業系統指紋辨識漏洞
Chromium 148 透過 Math.tanh 引入作業系統層級的指紋辨識
從 Chromium 148 開始,V8 中的 Math.tanh 函數已成為一種可被指紋辨識的訊號,允許網站辨識使用者的底層作業系統。這是因為 V8 將其內建的、可移植的 fdlibm 版本替換為 std::tanh,後者會呼叫主機作業系統的原生數學函式庫 (libm)。
由於不同的作業系統使用不同的數學函式庫——Linux 使用 glibc,macOS 使用 libsystem_m,以及 Windows 使用 UCRT——它們在處理超越函數時會產生略微不同的近似值。單次呼叫 Math.tanh(0.8) 即可區分這三個平台,因為它們在結果的最後幾位元(最後一位單位,或稱 ULP)上存在差異。
作業系統特定的數學特徵碼
在 Chrome 150 中執行 Math.tanh(0.8),各平台的結果如下:
- Linux (glibc):
0.6640367702678491 - macOS (libsystem_m):
0.664036770267849 - Windows (UCRT):
0.6640367702678489
這對於任何偽裝 User-Agent 的瀏覽器來說都造成了矛盾。如果一個瀏覽器聲稱自己是在 macOS 上運行,但卻回傳了 Linux 特有的數學位元,反機器人系統可以立即將該工作階段標記為欺詐。
技術根本原因:libm 分歧
IEEE 754 定義了浮點數的儲存方式,但它並不要求 sin、cos 或 tanh 等函數必須進行正確捨入。因此,作業系統供應商會使用不同的 minimax 係數、查找表和簡化常數來實作自己的 libm 函式庫,以平衡速度與精確度。
V8 的變更
在 Chrome 148 之前,V8 使用內建的 fdlibm 實作,確保所有平台的結果完全一致。在 V8 commit c1486295ae5 中的 std::tanh 轉換,將運算轉移到了主機的 libm,從而引入了作業系統洩漏。雖然 V8 中的大多數 Math.* 函數仍保持內建(透過 llvm-libc 或 dbl-64),但 Math.tanh 目前是唯一會洩漏主機作業系統的 JavaScript 數學函數。
映射指紋辨識表面積
透過數學進行指紋辨識並不侷限於 Math.tanh。不同的瀏覽器組件會透過不同的函式庫路由數學呼叫,從而產生多個洩漏向量:
| 操作 | V8 Math.* (JS) |
CSS calc() |
Web Audio |
|---|---|---|---|
sin, cos, tan |
V8 內建 (安全) | 主機 libm (洩漏) | Accelerate (Mac) / Scalar (Compressor) |
asin, acos, atan, atan2 |
V8 內建 (安全) | 主機 libm (洩漏) | 未使用 |
tanh |
主機 libm (洩漏) | 無 | 未使用 |
exp, log, pow |
V8 內建 (安全) | 主機 libm (洩漏) | Scalar (Compressor) |
| Vector/FFT | N/A | N/A | Accelerate (Mac) |
洩漏表面積的關鍵發現
- CSS 三角函數: 所有七種 CSS 三角函數都會洩漏作業系統,因為 Blink 渲染引擎會直接呼叫主機
libm。 - Web Audio (macOS): 在 Mac 上,Chrome 使用 Apple 的 Accelerate 框架進行 FFT 和向量數學運算,但對於 DynamicsCompressor 使用純量 (scalar)
libsystem_m。這意味著單個音訊圖形 (audio graph) 可能會洩漏兩種不同的 Apple 數學特徵碼。 - WASM: WebAssembly 的數學運算在各作業系統之間通常是完全一致的,因為它內建了自己的
libm或使用硬體層級的算術運算,儘管它仍可能透過 NaN 正規化 (canonicalization) 洩漏 CPU 架構 (ARM vs x86)。
緩解數學指紋辨識的策略
簡單的雜訊注入(在輸出中加入隨機值)是無效的,因為這這會產生一個與任何已知作業系統都不匹配的結果,從而破壞了決定性 (determinism),而決定性本身就是一種可被偵測的訊號。
精確演算法重現
為了成功偽裝作業系統,實作必須精確地重現目標的 libm,包括其特定的 minimax 係數和捨入誤差。這需要:
- 逐字係數: 從目標函式庫(例如 Apple 的
libsystem_m)複製係數的位元模式,而不是使用十進位近似值。 n2. FMA 控制: 使用顯式的融合乘加 (fma()) 呼叫,並禁用編譯器 FMA 縮減 (-ffp-contract=off),以確保結果在不同 CPU 架構(ARM vs x86)上具有位元一致性。
函式庫提升 (Library Lifting)
對於 Windows UCRT,可以將真實的 ucrtbase.dll 映射到 Linux 程序的記憶體中。這需要處理 Windows x64 ABI(在 Clang 中使用 ms_abi)以避免堆疊損壞,並強制 CPU 分派路徑至 FMA 路徑,以匹配現代 Windows 硬體的操作結果。
社群觀點與反論點
技術觀察者的討論突顯了關於此漏洞的幾個細微差別:
"Recent glibc uses the correctly rounded tanh from CORE-MATH, so it returns different values than what's quoted in the article."
一些使用者指出,這項漏洞可能對於指紋辨識特定的瀏覽器版本範圍比單純辨識作業系統更有用,因為大多數使用者不會偽裝 User-Agent。其他人則認為,指紋辨識向量(IP、螢幕解析度等)的對稱性 ubiquitous (遍布性) 使這項特定的洩漏成為對已受損隱私-環境中微不足道的補充。