
CVE-2025-36911: Fast Pair Pairing Mode Bypass 취약점을 식별하고 시연하는 보안 연구 도구
CVE-2025-36911과 Google Fast Pair 생태계의 보안 취약점에 대한 심층 분석
Google Fast Pair는 Bluetooth 페어링을 매끄럽게 만들기 위해 설계되었습니다. 알림을 탭하면 연결되는 방식입니다. 하지만 이 매끄러운 경험이 보안상의 책임이 되면 어떻게 될까요? WhisperPair-PoC-Tool은 수백만 개의 Bluetooth 액세서리에 영향을 미치는 두 가지 중요한 취약점 클래스, 즉 무단 페어링 우회와 Find My Device 네트워크 추적 악용을 드러내는 보안 연구 도구입니다.
이 글은 WhisperPair-PoC-Tool의 기술적 내부 구조, 이 도구가 악용하는 프로토콜 취약점, 그리고 이것이 Bluetooth 액세서리 생태계에 의미하는 바를 자세히 설명합니다.
Google Fast Pair 사양은 명시적으로 다음과 같이 명시합니다:
"선택적 공개 키(Public Key) 필드가 있는 경우: 기기가 페어링 모드가 아니면 쓰기를 무시하고 종료합니다."
이것이 중요한 보안 관문입니다. 기기는 사용자가 명시적으로 페어링 모드로 전환한 경우(일반적으로 버튼을 길게 누름)에만 키 기반 페어링(Key-Based Pairing) 요청에 응답해야 합니다. 이는 사용자 의도를 보장하므로, 상대방이 착용 중인 이어버드에 페어링할 수 없습니다.
문제점: 많은 제조사가 이 검사를 완전히 건너뜁니다. 페어링 모드 상태와 관계없이 페어링 요청을 처리하여 다음과 같은 문제를 가능하게 합니다:
Google의 Find My Device 네트워크(FMDN)는 크라우드소싱된 Android 기기 네트워크를 통해 Bluetooth 액세서리를 추적할 수 있게 해줍니다. 이를 위해서는 기기를 Google 계정에 연결하는 16바이트 대칭 키인 **계정 키(Account Key)**가 필요합니다.
문제점: Account Key 특성(characteristic)은 인증 없이 쓰기를 허용하는 경우가 많습니다:
악용에 대해 자세히 살펴보기 전에, 정상적인 Fast Pair 흐름을 이해해 봅시다:
┌─────────────────────────────────────────────────────────────┐
│ BLE Advertisement │
├─────────────────────────────────────────────────────────────┤
│ Service UUID: 0xFE2C (Fast Pair) │
│ Service Data: │
│ [Pairing Mode] → 3 bytes: Model ID only │
│ [Not Pairing] → 4+ bytes: 0x00 + Account Key Filter │
└─────────────────────────────────────────────────────────────┘
광고 형식은 페어링 상태를 드러냅니다:
Seeker (Phone) Provider (Accessory)
│ │
│───── GATT Connect ──────────────────────────>│
│ │
│───── Discover Services ─────────────────────>│
│<──── Service: 0xFE2C ────────────────────────│
│ │
│───── Enable Notifications (0xFE2C1234) ─────>│
│ │
│───── Write Key-Based Pairing Request ───────>│
│ [16-byte encrypted block] │
│ [64-byte ECDH Public Key] (optional) │
│ │
│ ┌────────────────────────────────────┐ │
│ │ SECURITY CHECK: │ │
│ │ If Public Key present AND │ │
│ │ device NOT in pairing mode: │ │
│ │ → IGNORE and EXIT │ │
│ │ Else: │ │
│ │ → Process request │ │
│ └────────────────────────────────────┘ │
│ │
│<──── Notification: Encrypted Response ───────│
│ [Provider's BR/EDR Address] │
│ │
│═══════ Bluetooth Classic Pairing ═══════════>│
취약점은 기기가 'SECURITY CHECK' 상자를 완전히 건너뛸 때 발생합니다.
WhisperPair-PoC-Tool은 Bleak BLE 라이브러리 기반의 Python 기반 보안 연구 도구입니다. 여러 단계로 작동합니다:
┌────────────────────────────────────────────────────────────────┐
│ WhisperPair-PoC-Tool │
├────────────────────────────────────────────────────────────────┤
│ CLI Layer │
│ ├── Argument parsing (--target-name, --scan-duration) │
│ ├── TargetPolicy construction │
│ └── REPL initialization │
├────────────────────────────────────────────────────────────────┤
│ Discovery Engine │
│ ├── BLE scanning via Bleak │
│ ├── Advertisement parsing │
│ ├── Protocol detection (Fast Pair, FMDN, Swift Pair) │
│ └── Device fingerprinting (Model ID, OUI lookup) │
├────────────────────────────────────────────────────────────────┤
│ Check Engines │
│ ├── FastPairCheckEngine (passive advertisement analysis) │
│ ├── FastPairBypass (active CVE-2025-36911 testing) │
│ ├── FindHubCheckEngine (Account Key status detection) │
│ └── RiskScorer (composite vulnerability assessment) │
├────────────────────────────────────────────────────────────────┤
│ Connection Manager │
│ ├── GATT connect with MTU negotiation │
│ ├── Service/characteristic discovery │
│ ├── Read/Write/Notify operations │
│ └── Error handling and retry logic │
├────────────────────────────────────────────────────────────────┤
│ Exploitation Modules │
│ ├── ring_device() - Trigger locator sound │
│ ├── set_account_key() - Write Account Key │
│ └── Response parsing (BR/EDR address extraction) │
└────────────────────────────────────────────────────────────────┘
discovery.py)스캐너는 Bleak의 탐지 콜백을 사용하여 BLE 광고를 캡처합니다:
async def _detection_callback(
self, device: BLEDevice, advertisement_data: AdvertisementData
) -> None:
"""Process each detected BLE advertisement."""
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:
"""Analyze Fast Pair service data to infer pairing mode."""
data = evidence.service_data_bytes
# 3 bytes = Model ID only = Pairing Mode (discoverable)
if len(data) == 3:
evidence.inferred_pairing_mode = PairingModeState.IN_PAIRING_MODE
return
# 4+ bytes with version 0x00 = Not in pairing mode
if data[0] == 0x00:
akd_byte = data[1]
akd_type = akd_byte & 0x0F # Lower 4 bits
# Type 0x00 = Show UI, Type 0x02 = Hide UI
# Both indicate NOT in pairing mode
evidence.inferred_pairing_mode = PairingModeState.NOT_IN_PAIRING_MODE
이것이 중요합니다. 기기가 페어링 모드가 아닌 것으로 확인되었는데도 페어링 요청에 응답한다면 취약한 것입니다.
fastpair_attack.py)핵심 취약점 테스트는 키 기반 페어링 요청을 보내고 응답을 모니터링합니다:
async def check_vulnerability(self, device: DiscoveredDevice) -> BypassCheckResult:
"""Test if device responds to pairing requests when not in pairing mode."""
# Enable notifications to receive response
await self.connection_manager.start_notify(
KEY_BASED_PAIRING_CHAR,
self._notification_handler,
)
# Build and send request (multiple strategies)
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,
)
# Wait for response
try:
await asyncio.wait_for(
self._response_received.wait(),
timeout=self.response_timeout,
)
# Response received = VULNERABLE
return BypassCheckResult(result=BypassResult.VULNERABLE, ...)
except asyncio.TimeoutError:
# No response = Device correctly ignored request
continue
return BypassCheckResult(result=BypassResult.NOT_VULNERABLE, ...)
도구는 여러 요청 전략을 구현합니다. 기기마다 서로 다른 플래그 조합에 응답하기 때문입니다:
취약한 기기가 응답하면 도구는 BR/EDR(Bluetooth Classic) 주소를 추출합니다:
def _parse_response(self, response_data: bytes) -> str | None:
"""Extract provider's BR/EDR address from response."""
# Strategy 1: Standard response (type 0x01)
if response_data[0] == 0x01:
return self._extract_address(response_data, offset=1)
# Strategy 2: Extended response (type 0x02)
if response_data[0] == 0x02:
addr_count = response_data[2]
return self._extract_address(response_data, offset=3)
# Strategy 3: Brute force pattern matching
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은 탐지 단계까지만 수행합니다).
연구를 통해 일반적인 구현 실패 사례가 확인되었습니다:
가장 흔한 문제: 제조사가 단순히 검사를 구현하지 않습니다:
// VULNERABLE: No pairing mode check
void handle_kbp_write(uint8_t* data, size_t len) {
if (len >= 80 && has_public_key(data)) {
// Should check: if (!is_in_pairing_mode()) return;
process_pairing_request(data); // Processes regardless
}
}
Account Key 특성은 인증을 요구해야 합니다:
// VULNERABLE: No authentication required
void handle_account_key_write(uint8_t* key, size_t len) {
if (len == 16) {
store_account_key(key); // Accepts any key from anyone
}
}
// SECURE: Verify caller knows existing key
void handle_account_key_write_secure(uint8_t* encrypted_key, size_t len) {
if (!verify_encrypted_with_existing_key(encrypted_key)) {
return; // Reject unauthorized writes
}
store_account_key(decrypt(encrypted_key));
}
페어링 모드가 아닌 상태에서 Fast Pair 서비스 데이터를 광고하는 기기는 다음 정보를 노출합니다:
WhisperPair-PoC-Tool은 계층적 탐지 방식을 사용합니다:
연결이 필요 없습니다. 도구는 기기가 브로드캐스트하는 내용을 분석합니다:
┌─────────────────────────────────────────────────────────────┐
│ Passive Checks │
├─────────────────────────────────────────────────────────────┤
│ ✓ Fast Pair service UUID present (0xFE2C) │
│ ✓ FMDN service UUID present (0xFD44) │
│ ✓ Pairing mode inferred from service data length │
│ ✓ Model ID extracted (when in pairing mode) │
│ ✓ Account Key Filter detected (when not in pairing mode) │
│ ✓ Address type analysis (static vs. random) │
└─────────────────────────────────────────────────────────────┘
Result: "Device advertising Fast Pair data while NOT in pairing mode"
→ Potential gating violation (needs active test to confirm)
연결이 필요합니다. 도구가 GATT 서비스와 상호작용합니다:
┌─────────────────────────────────────────────────────────────┐
│ Active Checks │
├─────────────────────────────────────────────────────────────┤
│ 1. Connect to device via BLE │
│ 2. Discover Fast Pair service (0xFE2C) │
│ 3. Locate Key-Based Pairing characteristic (0xFE2C1234) │
│ 4. Enable notifications │
│ 5. Write Key-Based Pairing request │
│ 6. Wait for response (with timeout) │
│ 7. Response received → VULNERABLE │
│ Timeout/Rejected → NOT VULNERABLE │
└─────────────────────────────────────────────────────────────┘
복합 위험 점수가 계산됩니다:
위험 수준:
WhisperPair-PoC-Tool은 영향을 입증하기 위한 통제된 악용 기능을 포함합니다:
ring 명령)FMDN Beacon Actions 특성을 트리거하여 위치 알림음을 재생합니다:
공개 버전에서는 삭제됨
영향: 공격자는 소리를 반복적으로 트리거하여 피해자를 괴롭히거나, 훔치려는 기기의 위치를 파악하는 데 사용할 수 있습니다.
set account-key 명령)새 Account Key를 기기에 씁니다:
공개 버전에서는 삭제됨
영향:
WhisperPair-PoC-Tool은 의도적으로 완전한 악용 직전까지만 수행합니다:
if (has_public_key(request) && !is_in_pairing_mode()) {
return; // Ignore request per spec
}
Account Key 쓰기에 대한 인증 요구:
광고 노출 최소화:
펌웨어 업데이트 메커니즘:
이 도구는 다음 용도로 사용됩니다:
WhisperPair-PoC-Tool은 '매끄러운' Fast Pair 경험에 많은 제조사가 해결하지 못하는 보안상의 트레이드오프가 수반됨을 보여줍니다. 페어링 모드 검사는 안전한 기기와 취약한 기기를 가르는 단 하나의 조건문이지만, 자주 누락됩니다.
Fast Pair의 신뢰 모델은 기기가 사용자 의도를 강제할 것이라고 가정합니다. 그렇지 않을 경우 공격자는 피해자 기기를 대상으로 무음 페어링, 추적 기능, 서비스 거부(DoS) 벡터를 얻게 됩니다.
이 도구는 생태계가 이러한 문제를 식별하고 수정하여 모든 사람을 위한 더 안전한 Bluetooth 액세서리를 만드는 데 기여하는 것을 목표로 합니다.
WhisperPair-PoC-Tool은 승인된 보안 연구 목적으로만 배포됩니다. 이 도구의 오용에 대한 책임은 지지 않습니다.
| 전략 | 플래그 | 설명 |
|---|
RAW_KBP | 0x11 | INITIATE_BONDING | EXTENDED_RESPONSE |
WITH_PUBLIC_KEY | 0x11 | ECDH 공개 키가 포함된 80바이트 요청 |
RETROACTIVE | 0x0A | 일부 제조사 검사를 우회함 |
EXTENDED | 0x10 | 최신 기기 펌웨어용 |
| 신호 | 점수 | 의미 |
|---|
| 게이팅 위반(수동) | +2 | 페어링 모드가 아닌데 FP 광고 |
| 우회 확인(능동) | +2 | 페어링 모드가 아닌데 KBP에 응답 |
| Account Key 없는 FMDN | +2 | Find My 네트워크를 통해 추적 가능 |
| 정적 BLE 주소 | +1 | 기기가 지속적으로 추적 가능 |
| 주소 회전 관찰됨 | -1 | 개인정보 보호 동작 |
| 기능 | 구현 여부 | 이유 |
|---|
| 취약점 탐지 | ✅ 예 | 핵심 목적 |
| BR/EDR 주소 추출 | ✅ 예 | 증거 수집 |
| Bluetooth Classic 페어링 | ❌ 아니요 | 플랫폼별 코드 필요 |
| HFP 오디오 하이재킹 | ❌ 아니요 | BLE 도구 범위를 벗어남 |
| 지속형 임플란트 | ❌ 아니요 | 악성 기능 |