深入探究 CVE-2025-36911 及 Google Fast Pair 生态系统中的安全漏洞
Google Fast Pair 旨在让蓝牙配对变得无缝:轻触通知即可连接。但当这种无缝体验变成安全负担时会发生什么?WhisperPair-PoC-Tool 是一款安全研究工具,它揭示了影响数百万蓝牙配件的两类关键漏洞:未授权配对绕过和 Find My Device 网络追踪利用。
本文详细介绍了 WhisperPair-PoC-Tool 的技术内部原理、它所利用的协议缺陷,以及这对蓝牙配件生态系统意味着什么。
Google Fast Pair 规范明确声明:
“如果可选的公钥字段存在:若设备未处于配对模式,则忽略写入并退出。”
这是关键的安全关卡。设备应仅在用户明确将设备置于配对模式(通常通过按住按钮)时,才对基于密钥的配对请求做出响应。这确保了用户意图,因此你无法在别人佩戴耳机时与其配对。
问题所在: 许多制造商完全跳过了这一检查。无论配对模式状态如何,它们都会处理配对请求,从而允许:
Google 的 Find My Device 网络 (FMDN) 允许通过众包的 Android 设备网络追踪蓝牙配件。这需要一个账户密钥,一个 16 字节的对称密钥,用于将设备链接到 Google 账户。
问题所在: 账户密钥特征通常接受写入操作而无需身份验证:
在深入探讨利用之前,让我们先了解合法的 Fast Pair 流程:
┌─────────────────────────────────────────────────────────────┐
│ BLE 广播 │
├─────────────────────────────────────────────────────────────┤
│ 服务 UUID: 0xFE2C (Fast Pair) │
│ 服务数据: │
│ [配对模式] → 3 字节:仅 Model ID │
│ [非配对模式] → 4+ 字节:0x00 + Account Key Filter │
└─────────────────────────────────────────────────────────────┘
广播格式揭示了配对状态:
Seeker (手机) Provider (配件)
│ │
│───── GATT 连接 ──────────────────────────────>│
│ │
│───── 发现服务 ───────────────────────────────>│
│<──── 服务: 0xFE2C ────────────────────────────│
│ │
│───── 启用通知 (0xFE2C1234) ──────────────────>│
│ │
│───── 写入基于密钥的配对请求 ──────────────────>│
│ [16 字节加密块] │
│ [64 字节 ECDH 公钥] (可选) │
│ │
│ ┌────────────────────────────────────┐ │
│ │ 安全检查: │ │
│ │ 如果存在公钥 且 │ │
│ │ 设备未处于配对模式: │ │
│ │ → 忽略并退出 │ │
│ │ 否则: │ │
│ │ → 处理请求 │ │
│ └────────────────────────────────────┘ │
│ │
│<──── 通知:加密响应 ──────────────────────────│
│ [Provider 的 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 (复合漏洞评估) │
├────────────────────────────────────────────────────────────────┤
│ 连接管理器 │
│ ├── GATT 连接及 MTU 协商 │
│ ├── 服务/特征发现 │
│ ├── 读/写/通知操作 │
│ └── 错误处理与重试逻辑 │
├────────────────────────────────────────────────────────────────┤
│ 利用模块 │
│ ├── 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)核心漏洞测试发送基于密钥的配对请求并监视响应:
async def check_vulnerability(self, device: DiscoveredDevice) -> BypassCheckResult:
"""测试设备在未处于配对模式时是否响应配对请求。"""
# 启用通知以接收响应
await self.connection_manager.start_notify(
KEY_BASED_PAIRING_CHAR,
self._notification_handler,
)
# 构建并发送请求(多种策略)
for strategy in self.strategies:
request, flags = self._build_strategy_request(device.address, strategy)
await self.connection_manager.write_characteristic(
KEY_BASED_PAIRING_CHAR,
request,
)
# 等待响应
try:
await asyncio.wait_for(
self._response_received.wait(),
timeout=self.response_timeout,
)
# 收到响应 = 存在漏洞
return BypassCheckResult(result=BypassResult.VULNERABLE, ...)
except asyncio.TimeoutError:
# 无响应 = 设备正确忽略了请求
continue
return BypassCheckResult(result=BypassResult.NOT_VULNERABLE, ...)
该工具实现了多种请求策略,因为不同设备响应不同的标志组合:
当易受攻击的设备响应时,该工具提取 BR/EDR(Bluetooth Classic)地址:
def _parse_response(self, response_data: bytes) -> str | None:
"""从响应中提取提供者的 BR/EDR 地址。"""
# 策略 1:标准响应(类型 0x01)
if response_data[0] == 0x01:
return self._extract_address(response_data, offset=1)
# 策略 2:扩展响应(类型 0x02)
if response_data[0] == 0x02:
addr_count = response_data[2]
return self._extract_address(response_data, offset=3)
# 策略 3:暴力模式匹配
for offset in range(len(response_data) - 5):
addr = self._extract_address(response_data, offset)
if self._is_valid_mac(addr):
return addr
这个 BR/EDR 地址可用于发起 Bluetooth Classic 配对(但 WhisperPair-PoC-Tool 在检测阶段停止)。
研究发现了常见的实现缺陷:
最常见的问题:制造商根本没有实现检查:
// 易受攻击:没有配对模式检查
void handle_kbp_write(uint8_t* data, size_t len) {
if (len >= 80 && has_public_key(data)) {
// 应检查: if (!is_in_pairing_mode()) return;
process_pairing_request(data); // 无论状态都处理
}
}
账户密钥特征应要求身份验证:
// 易受攻击:无身份验证要求
void handle_account_key_write(uint8_t* key, size_t len) {
if (len == 16) {
store_account_key(key); // 接受来自任何人的任何密钥
}
}
// 安全:验证调用者知道现有密钥
void handle_account_key_write_secure(uint8_t* encrypted_key, size_t len) {
if (!verify_encrypted_with_existing_key(encrypted_key)) {
return; // 拒绝未授权的写入
}
store_account_key(decrypt(encrypted_key));
}
设备在未处于配对模式时广播 Fast Pair 服务数据会暴露:
WhisperPair-PoC-Tool 采用分层检测方法:
无需连接。 该工具分析设备广播的内容:
┌─────────────────────────────────────────────────────────────┐
│ 被动检查 │
├─────────────────────────────────────────────────────────────┤
│ ✓ Fast Pair 服务 UUID 存在 (0xFE2C) │
│ ✓ FMDN 服务 UUID 存在 (0xFD44) │
│ ✓ 通过服务数据长度推断配对模式 │
│ ✓ 提取 Model ID(处于配对模式时) │
│ ✓ 检测账户密钥过滤器(未处于配对模式时) │
│ ✓ 地址类型分析(静态 vs 随机) │
└─────────────────────────────────────────────────────────────┘
结果: "设备在未处于配对模式时广播 Fast Pair 数据"
→ 潜在的门控违规(需要主动测试确认)
需要连接。 该工具与 GATT 服务交互:
┌─────────────────────────────────────────────────────────────┐
│ 主动检查 │
├─────────────────────────────────────────────────────────────┤
│ 1. 通过 BLE 连接设备 │
│ 2. 发现 Fast Pair 服务 (0xFE2C) │
│ 3. 定位基于密钥的配对特征 (0xFE2C1234) │
│ 4. 启用通知 │
│ 5. 写入基于密钥的配对请求 │
│ 6. 等待响应(带超时) │
│ 7. 收到响应 → 易受攻击 │
│ 超时/拒绝 → 不易受攻击 │
└─────────────────────────────────────────────────────────────┘
计算综合风险评分:
风险等级:
WhisperPair-PoC-Tool 包含受控的利用功能以演示影响:
ring 命令)触发 FMDN Beacon Actions 特征以播放定位声音:
REDACTED FOR RELEASE
影响: 攻击者可以通过重复触发声音骚扰受害者,或利用它定位他们想要偷窃的设备。
set account-key 命令)向设备写入新的账户密钥:
REDACTED FOR RELEASE
影响:
WhisperPair-PoC-Tool 有意在完全利用前停止:
if (has_public_key(request) && !is_in_pairing_mode()) {
return; // 根据规范忽略请求
}
要求账户密钥写入的身份验证:
最小化广播暴露:
固件更新机制:
此工具旨在用于:
WhisperPair-PoC-Tool 表明,“无缝”的 Fast Pair 体验伴随着许多制造商未能解决的安全权衡。配对模式检查是一个简单的条件语句,却将安全设备与易受攻击设备区分开来,但这一检查经常被忽略。
Fast Pair 的信任模型假设设备会强制执行用户意图。当它们不执行时,攻击者便能获得静默配对、追踪能力以及针对受害者设备的拒绝服务向量。
此工具旨在帮助生态系统识别并修复这些问题,使蓝牙配件对每个人都更安全。
WhisperPair-PoC-Tool 仅用于授权的安全研究。对于滥用此工具不承担任何责任。
| 策略 | 标志 | 描述 |
|---|
RAW_KBP | 0x11 | INITIATE_BONDING | EXTENDED_RESPONSE |
WITH_PUBLIC_KEY | 0x11 | 80 字节请求,包含 ECDH 公钥 |
RETROACTIVE | 0x0A | 绕过某些制造商的检查 |
EXTENDED | 0x10 | 针对较新的设备固件 |
| 信号 | 分数 | 含义 |
|---|
| 门控违规(被动) | +2 | 未处于配对模式时广播 FP 数据 |
| 确认绕过(主动) | +2 | 未处于配对模式时响应 KBP |
| 无账户密钥的 FMDN | +2 | 可通过 Find My 网络追踪 |
| 静态 BLE 地址 | +1 | 设备可持久追踪 |
| 观察到地址轮换 | -1 | 隐私保护行为 |
| 能力 | 已实现 | 原因 |
|---|
| 漏洞检测 | ✅ 是 | 核心目的 |
| BR/EDR 地址提取 | ✅ 是 | 证据收集 |
| Bluetooth Classic 配对 | ❌ 否 | 需要平台特定代码 |
| HFP 音频劫持 | ❌ 否 | 超出 BLE 工具范围 |
| 持久性植入 | ❌ 否 | 恶意能力 |