
Un outil de recherche en sécurité qui identifie et démontre la vulnérabilité CVE-2025-36911 : Fast Pair Pairing Mode Bypass
Une analyse approfondie de CVE-2025-36911 et des lacunes de sécurité dans l'écosystème Fast Pair de Google
Google Fast Pair a été conçu pour rendre l'appairage Bluetooth transparent : une simple notification et vous êtes connecté. Mais que se passe-t-il lorsque cette expérience transparente devient une faille de sécurité ? WhisperPair-PoC-Tool est un outil de recherche en sécurité qui expose deux classes de vulnérabilités critiques affectant des millions d'accessoires Bluetooth : le contournement de l'appairage non autorisé et l'exploitation du réseau Find My Device.
Ce billet détaille le fonctionnement interne de WhisperPair-PoC-Tool, les faiblesses de protocole qu'il exploite et ce que cela signifie pour l'écosystème des accessoires Bluetooth.
La spécification Google Fast Pair précise explicitement :
"Si le champ optionnel Clé Publique est présent : si l'appareil n'est pas en mode appairage, ignorez l'écriture et quittez."
C'est la barrière de sécurité critique. Les appareils devraient uniquement répondre aux demandes d'appairage basées sur une clé lorsque l'utilisateur a explicitement mis l'appareil en mode appairage (généralement en maintenant un bouton enfoncé). Cela garantit l'intention de l'utilisateur, afin que vous ne puissiez pas vous appairer avec les écouteurs de quelqu'un pendant qu'il les porte.
Le Problème : De nombreux fabricants ignorent complètement cette vérification. Ils traitent les demandes d'appairage quel que soit l'état du mode appairage, permettant :
Le réseau Find My Device (FMDN) de Google permet de suivre les accessoires Bluetooth via le réseau d'appareils Android participatif. Pour cela, une Clé de Compte (Account Key) est nécessaire, une clé symétrique de 16 octets qui lie l'appareil à un compte Google.
Le Problème : La caractéristique Account Key accepte souvent des écritures sans authentification :
Avant de plonger dans l'exploitation, comprenons le flux légitime de Fast Pair :
┌─────────────────────────────────────────────────────────────┐
│ Annonce BLE │
├─────────────────────────────────────────────────────────────┤
│ UUID de service : 0xFE2C (Fast Pair) │
│ Données de service : │
│ [Mode d'appairage] → 3 octets : uniquement Model ID │
│ [Pas en appairage] → 4+ octets : 0x00 + Filtre Clé │
└─────────────────────────────────────────────────────────────┘
Le format d'annonce révèle l'état d'appairage :
Chercheur (Téléphone) Fournisseur (Accessoire)
│ │
│───── Connexion GATT ─────────────────────────>│
│ │
│───── Découverte des Services ────────────────>│
│<──── Service : 0xFE2C ────────────────────────│
│ │
│───── Activer Notifications (0xFE2C1234) ────>│
│ │
│───── Écrire Requête d'Appairage Basée Clé ──>│
│ [bloc chiffré de 16 octets] │
│ [Clé Publique ECDH de 64 octets] (opt.) │
│ │
│ ┌────────────────────────────────────┐ │
│ │ VÉRIFICATION DE SÉCURITÉ : │ │
│ │ Si Clé Publique présente ET │ │
│ │ appareil PAS en mode appairage : │ │
│ │ → IGNORER et QUITTER │ │
│ │ Sinon : │ │
│ │ → Traiter la requête │ │
│ └────────────────────────────────────┘ │
│ │
│<──── Notification : Réponse Chiffrée ────────│
│ [Adresse BR/EDR du Fournisseur] │
│ │
│═══════ Appairage Bluetooth Classique ════════>│
La vulnérabilité survient lorsque les appareils ignorent complètement la boîte "VÉRIFICATION DE SÉCURITÉ".
WhisperPair-PoC-Tool est un outil de recherche en sécurité basé sur Python, construit sur la bibliothèque BLE Bleak. Il fonctionne en plusieurs phases :
┌────────────────────────────────────────────────────────────────┐
│ WhisperPair-PoC-Tool │
├────────────────────────────────────────────────────────────────┤
│ Couche CLI │
│ ├── Analyse des arguments (--target-name, --scan-duration) │
│ ├── Construction de TargetPolicy │
│ └── Initialisation du REPL │
├────────────────────────────────────────────────────────────────┤
│ Moteur de Découverte │
│ ├── Scan BLE via Bleak │
│ ├── Analyse des annonces │
│ ├── Détection de protocole (Fast Pair, FMDN, Swift Pair) │
│ └── Empreinte de l'appareil (Model ID, consultation OUI) │
├────────────────────────────────────────────────────────────────┤
│ Moteurs de Vérification │
│ ├── FastPairCheckEngine (analyse passive des annonces) │
│ ├── FastPairBypass (test actif CVE-2025-36911) │
│ ├── FindHubCheckEngine (détection état de la Clé de Compte) │
│ └── RiskScorer (évaluation composite des vulnérabilités) │
├────────────────────────────────────────────────────────────────┤
│ Gestionnaire de Connexion │
│ ├── Connexion GATT avec négociation MTU │
│ ├── Découverte des services/caractéristiques │
│ ├── Opérations Lecture/Écriture/Notification │
│ └── Gestion des erreurs et logique de réessai │
├────────────────────────────────────────────────────────────────┤
│ Modules d'Exploitation │
│ ├── ring_device() - Déclencher son de localisation │
│ ├── set_account_key() - Écrire une Clé de Compte │
│ └── Analyse de la réponse (extraction adresse BR/EDR) │
└────────────────────────────────────────────────────────────────┘
discovery.py)Le scanner utilise les callbacks de détection de Bleak pour capturer les annonces BLE :
async def _detection_callback(
self, device: BLEDevice, advertisement_data: AdvertisementData
) -> None:
"""Traite chaque annonce BLE détectée."""
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
Pour chaque appareil, l'outil extrait :
0xFE2C, FMDN 0xFD44, etc.)0x00E0, Apple 0x004C)fastpair.py)Le mode d'appairage est déterminé en analysant l'annonce de l'appareil :
def _analyze_service_data(self, evidence: FastPairEvidence) -> None:
"""Analyse les données de service Fast Pair pour inférer le mode d'appairage."""
data = evidence.service_data_bytes
# 3 octets = Model ID uniquement = Mode appairage (découvrable)
if len(data) == 3:
evidence.inferred_pairing_mode = PairingModeState.IN_PAIRING_MODE
return
# 4+ octets avec version 0x00 = Pas en mode appairage
if data[0] == 0x00:
akd_byte = data[1]
akd_type = akd_byte & 0x0F # 4 bits de poids faible
# Type 0x00 = Afficher IU, Type 0x02 = Masquer IU
# Les deux indiquent PAS en mode appairage
evidence.inferred_pairing_mode = PairingModeState.NOT_IN_PAIRING_MODE
C'est crucial : si un appareil est déterminé comme n'étant pas en mode appairage et qu'il répond néanmoins à la demande d'appairage, il est vulnérable.
fastpair_attack.py)Le test de vulnérabilité principal envoie des demandes d'appairage basées sur une clé et surveille les réponses :
async def check_vulnerability(self, device: DiscoveredDevice) -> BypassCheckResult:
"""Teste si l'appareil répond aux demandes d'appairage lorsqu'il n'est pas en mode appairage."""
# Activer les notifications pour recevoir la réponse
await self.connection_manager.start_notify(
KEY_BASED_PAIRING_CHAR,
self._notification_handler,
)
# Construire et envoyer la demande (plusieurs stratégies)
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,
)
# Attendre une réponse
try:
await asyncio.wait_for(
self._response_received.wait(),
timeout=self.response_timeout,
)
# Réponse reçue = VULNÉRABLE
return BypassCheckResult(result=BypassResult.VULNERABLE, ...)
except asyncio.TimeoutError:
# Pas de réponse = L'appareil a correctement ignoré la demande
continue
return BypassCheckResult(result=BypassResult.NOT_VULNERABLE, ...)
L'outil implémente plusieurs stratégies de demande car différents appareils réagissent à différentes combinaisons de flags :
Lorsqu'un appareil vulnérable répond, l'outil extrait l'adresse BR/EDR (Bluetooth Classique) :
def _parse_response(self, response_data: bytes) -> str | None:
"""Extrait l'adresse BR/EDR du fournisseur depuis la réponse."""
# Stratégie 1 : Réponse standard (type 0x01)
if response_data[0] == 0x01:
return self._extract_address(response_data, offset=1)
# Stratégie 2 : Réponse étendue (type 0x02)
if response_data[0] == 0x02:
addr_count = response_data[2]
return self._extract_address(response_data, offset=3)
# Stratégie 3 : Correspondance de motif par force brute
for offset in range(len(response_data) - 5):
addr = self._extract_address(response_data, offset)
if self._is_valid_mac(addr):
return addr
Cette adresse BR/EDR pourrait être utilisée pour initier un appairage Bluetooth Classique (bien que WhisperPair-PoC-Tool s'arrête à la détection).
La recherche a identifié des défauts d'implémentation courants :
Le problème le plus fréquent : les fabricants n'implémentent tout simplement pas la vérification :
// VULNÉRABLE : Pas de vérification du mode d'appairage
void handle_kbp_write(uint8_t* data, size_t len) {
if (len >= 80 && has_public_key(data)) {
// Devrait vérifier : if (!is_in_pairing_mode()) return;
process_pairing_request(data); // Traite quoi qu'il arrive
}
}
La caractéristique Account Key devrait nécessiter une authentification :
// VULNÉRABLE : Aucune authentification requise
void handle_account_key_write(uint8_t* key, size_t len) {
if (len == 16) {
store_account_key(key); // Accepte n'importe quelle clé de n'importe qui
}
}
// SÉCURISÉ : Vérifier que l'appelant connaît la clé existante
void handle_account_key_write_secure(uint8_t* encrypted_key, size_t len) {
if (!verify_encrypted_with_existing_key(encrypted_key)) {
return; // Rejeter les écritures non autorisées
}
store_account_key(decrypt(encrypted_key));
}
Les appareils qui annoncent des données de service Fast Pair alors qu'ils ne sont pas en mode appairage révèlent :
WhisperPair-PoC-Tool utilise une approche de détection en couches :
Aucune connexion requise. L'outil analyse ce que l'appareil diffuse :
┌─────────────────────────────────────────────────────────────┐
│ Vérifications Passives │
├─────────────────────────────────────────────────────────────┤
│ ✓ UUID de service Fast Pair présent (0xFE2C) │
│ ✓ UUID de service FMDN présent (0xFD44) │
│ ✓ Mode d'appairage inféré depuis la longueur des données │
│ ✓ Model ID extrait (lorsqu'en mode appairage) │
│ ✓ Filtre de Clé de Compte détecté (hors mode appairage) │
│ ✓ Analyse du type d'adresse (statique vs aléatoire) │
└─────────────────────────────────────────────────────────────┘
Résultat : "L'appareil annonce des données Fast Pair alors qu'il n'est PAS en mode appairage"
→ Potentielle violation de barrière (nécessite un test actif pour confirmer)
Nécessite une connexion. L'outil interagit avec les services GATT :
┌─────────────────────────────────────────────────────────────┐
│ Vérifications Actives │
├─────────────────────────────────────────────────────────────┤
│ 1. Connexion à l'appareil via BLE │
│ 2. Découverte du service Fast Pair (0xFE2C) │
│ 3. Localisation de la caractéristique Key-Based Pairing │
│ (0xFE2C1234) │
│ 4. Activation des notifications │
│ 5. Écriture de la demande d'appairage basée sur clé │
│ 6. Attente d'une réponse (avec timeout) │
│ 7. Réponse reçue → VULNÉRABLE │
│ Timeout/Rejet → NON VULNÉRABLE │
└─────────────────────────────────────────────────────────────┘
Un score de risque composite est calculé :
Niveaux de Risque :
WhisperPair-PoC-Tool inclut des fonctionnalités d'exploitation contrôlées pour démontrer l'impact :
ring)Déclenche la caractéristique FMDN Beacon Actions pour jouer le son de localisation :
MASQUÉ POUR LA PUBLICATION
Impact : Un attaquant peut harceler une victime en déclenchant le son de manière répétée, ou l'utiliser pour localiser un appareil qu'il souhaite voler.
set account-key)Écrit une nouvelle Clé de Compte sur l'appareil :
MASQUÉ POUR LA PUBLICATION
Impact :
WhisperPair-PoC-Tool s'arrête intentionnellement avant l'exploitation complète :
if (has_public_key(request) && !is_in_pairing_mode()) {
return; // Ignorer la demande selon la spécification
}
Exiger une authentification pour les écritures de Clé de Compte :
Minimiser l'exposition des annonces :
Mécanisme de mise à jour du firmware :
Cet outil est destiné à :
WhisperPair-PoC-Tool démontre que l'expérience "transparente" de Fast Pair s'accompagne de compromis de sécurité que de nombreux fabricants ne traitent pas. La vérification du mode d'appairage est une simple condition qui sépare un appareil sécurisé d'un appareil vulnérable, et elle est pourtant fréquemment omise.
Le modèle de confiance de Fast Pair suppose que les appareils appliqueront l'intention de l'utilisateur. Lorsque ce n'est pas le cas, les attaquants obtiennent un appairage silencieux, des capacités de suivi et des vecteurs de déni de service contre les appareils des victimes.
Cet outil vise à aider l'écosystème à identifier et corriger ces problèmes, rendant les accessoires Bluetooth plus sûrs pour tout le monde.
WhisperPair-PoC-Tool est publié uniquement pour la recherche en sécurité autorisée. Aucune responsabilité n'est assumée en cas d'utilisation abusive de cet outil.
| Stratégie | Flags | Description |
|---|
RAW_KBP | 0x11 | INITIATE_BONDING | EXTENDED_RESPONSE |
WITH_PUBLIC_KEY | 0x11 | Demande de 80 octets avec clé publique ECDH |
RETROACTIVE | 0x0A | Contourne certains contrôles de fabricants |
EXTENDED | 0x10 | Pour les firmware plus récents |
| Signal | Score | Signification |
|---|
| Violation de barrière (passif) | +2 | Annonce Fast Pair sans être en mode appairage |
| Contournement confirmé (actif) | +2 | A répondu à KBP sans être en mode appairage |
| FMDN sans Clé de Compte | +2 | Traçable via le réseau Find My |
| Adresse BLE statique | +1 | L'appareil est traçable de manière persistante |
| Rotation d'adresse observée | -1 | Comportement respectueux de la vie privée |
| Capacité | Implémenté | Raison |
|---|
| Détection de vulnérabilité | ✅ Oui | Objectif principal |
| Extraction d’adresse BR/EDR | ✅ Oui | Collecte de preuves |
| Appairage Bluetooth Classique | ❌ Non | Nécessite du code spécifique à la plateforme |
| Détournement audio HFP | ❌ Non | Au-delà du périmètre de l'outil BLE |
| Implant persistant | ❌ Non | Capacité malveillante |