
CVE-2025-36911: Fast Pair Pairing Mode Bypass脆弱性を特定および実証するセキュリティ研究ツール。
CVE-2025-36911 と Google Fast Pair エコシステムのセキュリティ脆弱性の詳細分析
Google Fast Pair は、Bluetooth ペアリングをシームレスにするために設計されました。通知をタップするだけで接続完了です。しかし、そのシームレスな体験がセキュリティ上の負債になったらどうなるでしょうか? WhisperPair-PoC-Tool は、何百万もの Bluetooth アクセサリに影響を与える2つの重大な脆弱性クラス(不正なペアリングバイパスと Find My Device ネットワーク追跡の悪用)を暴露するセキュリティ研究ツールです。
この記事では、WhisperPair-PoC-Tool の技術的内部、それが悪用するプロトコルの弱点、そしてこれが Bluetooth アクセサリエコシステムにとって何を意味するのかを詳しく説明します。
Google Fast Pair 仕様書は明確に次のように述べています。
「オプションの公開鍵フィールドが存在する場合:デバイスがペアリングモードでなければ、書き込みを無視して終了する。」
これが重要なセキュリティゲートです。デバイスは、ユーザーが明示的にペアリングモード(通常はボタン長押し)にした場合にのみ、鍵ベースのペアリング要求に応答するべきです。これによりユーザーの意図が確保され、例えば装着中のイヤホンに勝手にペアリングされることはありません。
問題点: 多くのメーカーがこのチェックを完全にスキップしています。ペアリングモードの状態に関係なくペアリング要求を処理してしまい、次のようなことが可能になります。
Google の Find My Device ネットワーク(FMDN)は、クラウドソースの Android デバイスネットワークを介して Bluetooth アクセサリを追跡できるようにします。これには、デバイスを Google アカウントにリンクするためのアカウントキー(16バイトの対称鍵)が必要です。
問題点: アカウントキー特性(Characteristic)は、認証なしで書き込みを受け付けることがよくあります。
悪用の詳細に入る前に、正規の Fast Pair フローを理解しましょう。
┌─────────────────────────────────────────────────────────────┐
│ BLE アドバタイズ │
├─────────────────────────────────────────────────────────────┤
│ サービス UUID: 0xFE2C (Fast Pair) │
│ サービスデータ: │
│ [ペアリングモード] → 3 バイト: Model ID のみ │
│ [ペアリングモード以外] → 4 バイト以上: 0x00 + Account Key Filter │
└─────────────────────────────────────────────────────────────┘
アドバタイズの形式からペアリング状態がわかります。
Seeker (電話) Provider (アクセサリ)
│ │
│───── GATT 接続 ───────────────────────────>│
│ │
│───── サービス検出 ────────────────────────>│
│<──── サービス: 0xFE2C ───────────────────────│
│ │
│───── 通知有効化 (0xFE2C1234) ────────────>│
│ │
│───── 鍵ベースペアリング要求の書き込み ────>│
│ [16 バイト暗号化ブロック] │
│ [64 バイト ECDH 公開鍵] (オプション) │
│ │
│ ┌────────────────────────────────────┐ │
│ │ セキュリティチェック: │ │
│ │ 公開鍵が存在し、かつ │ │
│ │ デバイスがペアリングモードでない場合:│ │
│ │ → 無視して終了 │ │
│ │ それ以外: │ │
│ │ → 要求を処理 │ │
│ └────────────────────────────────────┘ │
│ │
│<──── 通知: 暗号化応答 ──────────────────────│
│ [プロバイダの BR/EDR アドレス] │
│ │
│═══════ Bluetooth Classic ペアリング ════════>│
脆弱性は、デバイスが「セキュリティチェック」ボックスを完全にスキップしたときに発生します。
WhisperPair-PoC-Tool は、Bleak BLE ライブラリ上に構築された Python ベースのセキュリティ研究ツールです。いくつかのフェーズで動作します。
┌────────────────────────────────────────────────────────────────┐
│ WhisperPair-PoC-Tool │
├────────────────────────────────────────────────────────────────┤
│ CLI 層 │
│ ├── 引数解析 (--target-name, --scan-duration) │
│ ├── TargetPolicy 構築 │
│ └── REPL 初期化 │
├────────────────────────────────────────────────────────────────┤
│ 検出エンジン │
│ ├── Bleak による BLE スキャン │
│ ├── アドバタイズ解析 │
│ ├── プロトコル検出 (Fast Pair, FMDN, Swift Pair) │
│ └── デバイスフィンガープリンティング (Model ID, OUI ルックアップ) │
├────────────────────────────────────────────────────────────────┤
│ チェックエンジン │
│ ├── FastPairCheckEngine (受動的アドバタイズ分析) │
│ ├── FastPairBypass (能動的 CVE-2025-36911 テスト) │
│ ├── FindHubCheckEngine (アカウントキーステータス検出) │
│ └── RiskScorer (複合脆弱性評価) │
├────────────────────────────────────────────────────────────────┤
│ 接続マネージャ │
│ ├── MTU ネゴシエーション付き GATT 接続 │
│ ├── サービス/特性 (Characteristic) 検出 │
│ ├── 読み取り/書き込み/通知操作 │
│ └── エラーハンドリングとリトライロジック │
├────────────────────────────────────────────────────────────────┤
│ 悪用モジュール │
│ ├── ring_device() - ロケーター音を鳴らす │
│ ├── set_account_key() - アカウントキーの書き込み │
│ └── 応答解析 (BR/EDR アドレス抽出) │
└────────────────────────────────────────────────────────────────┘
discovery.py)スキャナーは Bleak の検出コールバックを使用して BLE アドバタイズをキャプチャします。
async def _detection_callback(
self, device: BLEDevice, advertisement_data: AdvertisementData
) -> None:
"""検出された各 BLE アドバタイズを処理します。"""
discovered = DiscoveredDevice(
address=device.address,
name=device.name or advertisement_data.local_name,
rssi=advertisement_data.rssi,
advertisement=self._convert_advertisement(advertisement_data),
first_seen=datetime.now(UTC),
last_seen=datetime.now(UTC),
)
self._devices[device.address] = discovered
各デバイスについて、ツールは以下を抽出します。
0xFE2C、FMDN 0xFD44 などを検出)0x00E0、Apple 0x004C)fastpair.py)ペアリングモードは、デバイスのアドバタイズを分析して判定されます。
def _analyze_service_data(self, evidence: FastPairEvidence) -> None:
"""Fast Pair サービスデータを分析してペアリングモードを推測します。"""
data = evidence.service_data_bytes
# 3 バイト = Model ID のみ = ペアリングモード (発見可能)
if len(data) == 3:
evidence.inferred_pairing_mode = PairingModeState.IN_PAIRING_MODE
return
# 4 バイト以上でバージョン 0x00 = ペアリングモードではない
if data[0] == 0x00:
akd_byte = data[1]
akd_type = akd_byte & 0x0F # 下位 4 ビット
# タイプ 0x00 = UI 表示、タイプ 0x02 = UI 非表示
# どちらもペアリングモードではないことを示す
evidence.inferred_pairing_mode = PairingModeState.NOT_IN_PAIRING_MODE
これが重要です。デバイスがペアリングモードではないと判定されたにもかかわらず、ペアリング要求に応答する場合、そのデバイスは脆弱です。
fastpair_attack.py)コアとなる脆弱性テストは、鍵ベースのペアリング要求を送信し、応答を監視します。