概要
- Math.tanh を利用した新しいOSフィンガープリント手法の解説
- 各OSの libm実装差異 が数値の最下位ビットに現れる現象
- Chrome 148以降 でのみMath.tanhがOS依存になる理由
- CSSやWeb Audioなど他の経路の リーク状況の全体マップ
- 真の再現や 回避策 の難しさ・検証手法の紹介
ChromeのMath.tanhがOSフィンガープリントに使われる理由
- Math.tanh(0.8) の結果がOSごとに微妙に異なる現象
- 例: Linux (glibc): 0.6640367702678491
- macOS (libsystem_m): 0.664036770267849
- Windows (UCRT): 0.6640367702678489
- この違いは libmの実装差 によるもので、最下位ビットの違い(1ULP程度)がOS判別の手掛かり
- Chrome 147以前 はV8が独自のfdlibm移植を使っていたため、どのOSでも同じ値だった
- Chrome 148以降 はV8がOS標準のstd::tanhを呼ぶ設計に変更され、OSごとの差が現れる
- User-Agent偽装 と数値ビットパターンの不一致で「偽装」がバレるリスク
他のフィンガープリント経路とその特徴
- JavaScriptのMath. *
- ほぼ全ての関数はV8バンドル実装でOS非依存
- 例外は Math.tanh のみ(Chrome 148以降)、ここだけOS依存
- CSSの三角関数(sin, cos, atan2など)
- Blinkエンジンが直接OS libmに依存して計算
- すべてのCSS三角関数でOSビットパターンがリーク
- Web Audio API
- Macでは Accelerateフレームワーク や libsystem_m の両方を用途によって使い分け
- FFTやベクトル演算はAccelerate、DynamicsCompressorはlibsystem_m
- WASM
- トランセンデンタル関数はバンドルlibm依存でOS非依存
- 例外はNaNのcanonicalizationやSIMDの丸め処理(アーキテクチャ依存)
なぜOSごとにビットが異なるのか
- IEEE 754 は浮動小数点のストレージのみ規定、sin/cos/tanh/exp等の丸め精度は未規定
- 各OSのlibmは 速度優先の近似アルゴリズム を持ち、係数や定数が異なる
- そのため、 1ULP程度の差 が頻繁に発生し、OS判別の材料となる
再現や偽装が難しい理由
- 一部のみOS依存
- Math.tanhやCSS三角関数など、一部だけ違うため「全部偽装」すると逆に矛盾が生じる
- 同名関数でも用途・経路で異なる実装
- 例: Macのsinはlibsystem_mとAccelerateで異なる結果を返す
- アーキテクチャ(ARM/x86)差分
- FMA(fused-multiply-add)やNaN伝播の違い
- 真の再現にはlibmから係数・定数の抽出、FMA明示化、FMA contraction禁止等が必要
- 速度差もフィンガープリント対象
- ソフトウェアFMAは遅く、ハードウェアFMAは高速。速度比も判別材料
検証・バリデーション手法
- 実機オラクル
- 本物のMacで全経路の結果を取得し、差分を把握
- 本物のChromeをDevToolsプロトコル経由で操作し、出力を取得
- 約87万入力でbit-for-bit検証
- 境界値、サブノーマル、無限大、NaN等も網羅
- 再現実装が本物バイナリの機械語と同一結果を返すことを確認
まとめ:なぜ重要か
- 数値計算は決定的・高速・偽装困難
- 多くの偽装・ボットスタックが見逃しやすい
- OSフィンガープリントの「静かな強力信号」
- 防御側には強力な武器、スクレイピング側には大きなリスク
- 正確な再現には逆アセンブルや係数抽出など高度な作業が必要
参考:主要なリークマップ(簡易表)
| 操作 | JS Math.* | CSS calc() | Web Audio | |---------------------|-------------|--------------|-----------------------| | sin, cos, tan | V8バンドル | OS libm | Accelerate/Scalar | | asin, acos, atan2 | V8バンドル | OS libm | - | | tanh | OS libm | - | - | | exp, log, pow | V8バンドル | OS libm | Scalar | | sqrt, abs, +, -, * | ハードウェア | ハードウェア | ハードウェア |
太字 はOS依存でビットパターンが異なる箇所を示す
フィンガープリント回避の実践ポイント
- 本物のlibmバイナリを呼び出す、またはbit-for-bit再現実装を用意
- FMAの扱い・係数値・丸め規則・速度まで本物と一致させる
- 経路ごとの分岐(用途・引数ごとに使うライブラリを正確に模倣)
- 検証は大量の入力・境界ケースを含めてbit一致を確認
関連用語解説
- ULP(Unit in Last Place): 浮動小数点で最下位ビット1個分の差
- libm: 各OSの数学関数ライブラリ(例: glibc, libsystem_m, UCRT)
- FMA(fused-multiply-add): 乗算+加算を1命令で実行するCPU命令セット
- Accelerate: macOSの高速ベクトル演算ライブラリ
- DevTools Protocol: Chromeを外部から制御・検証するためのAPI
要点
- Chrome 148以降、 Math.tanh の値でOS判別が可能
- CSS三角関数やWeb Audioも OS/アーキテクチャ依存のビットパターン がリーク
- 再現や偽装には高度な逆アセンブル・実装力が必要
- 速度や経路選択もフィンガープリントの一部 として機能