Chromium 148 Math.tanh OS フィンガープリンティング脆弱性

Chromium 148 Math.tanh OS フィンガープリンティング脆弱性

Chromium 148 が Math.tanh を通じて OS レベルのフィンガープリンティングを導入

Chromium 148 以降、V8 の Math.tanh 関数がフィンガープリンティング可能なシグナルとなり、ウェブサイトがユーザーの基盤となるオペレーティングシステムを特定できるようになりました。これは、V8 がバンドルされたポータブルな fdlibm ポートを廃止し、ホスト OS のネイティブ数学ライブラリ(libm)を呼び出す std::tanh に置き換えたためです。

異なるオペレーティングシステムは異なる数学ライブラリ(Linux は glibc、macOS は libsystem_m、Windows は UCRT)を使用しているため、超越関数の近似が若干異なります。Math.tanh(0.8) を一度呼び出すだけで、結果の最下位ビット(ULP: Unit in the Last Place)が異なるため、これら三つのプラットフォームを区別できます。

OS 固有の数学シグネチャ

Chrome 150 で Math.tanh(0.8) を実行した場合、プラットフォームごとに結果が異なります:

  • Linux (glibc): 0.6640367702678491
  • macOS (libsystem_m): 0.664036770267849
  • Windows (UCRT): 0.6640367702678489

このため、User-Agent を偽装したブラウザが矛盾した結果を返すと、アンチボットシステムは即座にセッションを不正と判断できます。

技術的根本原因: libm の差異

IEEE 754 は浮動小数点数の格納方法を定義していますが、sincostanh などの関数が正しく丸められることは要求していません。そのため、OS ベンダーは速度と精度のバランスを取るために、異なる minimax 係数、ルックアップテーブル、縮小定数を用いて独自の libm を実装しています。

V8 の変更点

Chrome 148 以前は V8 がバンドルされた fdlibm 実装を使用しており、すべてのプラットフォームで同一の結果が得られていました。V8 のコミット c1486295ae5std::tanh に移行したことで、計算がホストの libm に委ねられ、OS 情報が漏洩するようになりました。ほとんどの Math.* 関数は依然として llvm-libcdbl-64 経由でバンドルされていますが、Math.tanh だけが現在ホスト OS を漏らす唯一の 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 の三角関数: Blink レンダリングエンジンがホスト libm を直接呼び出すため、7 つすべての CSS 三角関数が OS を漏らします。
  • Web Audio (macOS): Mac では Chrome が Apple の Accelerate フレームワークを FFT とベクトル演算に使用しますが、DynamicsCompressor にはスカラー libsystem_m を使用します。そのため、単一のオーディオグラフで 2 つの異なる Apple 数学シグネチャが漏洩します。
  • WASM: WebAssembly の数学は通常 OS 間で同一です。これは独自の libm をバンドルするか、ハードウェアレベルの演算を使用するためですが、NaN 正規化を通じて CPU アーキテクチャ(ARM vs x86)を漏らすことはあります。

Math フィンガープリンティング緩和策

単純なノイズ注入(出力にランダム値を加える)は効果がありません。なぜなら、既知の OS と一致しない結果となり、決定論的でなくなることで別の検出可能シグナルになるからです。

正確なアルゴリズム再現

OS を偽装するには、対象の libm をビット単位で正確に再現する必要があります。具体的には:

  1. 係数の逐語的コピー: 対象ライブラリ(例: Apple の libsystem_m)から係数のビットパターンをそのままコピーし、十進近似を使用しない。
  2. FMA 制御: 明示的な fused multiply‑add (fma()) 呼び出しを使用し、コンパイラの FMA 縮約を無効化(-ffp-contract=off)して、CPU アーキテクチャ間でビット同一の結果を保証する(ARM vs x86)。

ライブラリリフティング

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."

一部のユーザーは、この脆弱性は OS の特定よりも特定のブラウザバージョン範囲のフィンガープリンティングに有用であると指摘しています。多くのユーザーは User-Agent を偽装しないためです。また、IP アドレスや画面解像度など既存のフィンガープリンティングベクトルが多数存在するため、この漏洩は既に侵害されたプライバシー環境への僅かな追加に過ぎないという意見もあります。

Sources