Giriş
Üzerinde çalıştığım cihaz piyasada üç yıldır bulunan, tıbbi olmayan bir aktivite bilekliği. Üreticinin mobil uygulaması bağlandığında trafik şifreli, ancak BLE eşleştirme akışı dikkatlice incelendiğinde anahtarın cihazın seri numarasından üretildiği fark ediliyor.1
// not — Bu yazıdaki tüm testler bana ait, satın alınmış cihazlar üzerinde yapılmıştır. Üreticiye 90 gün önceden bildirim gönderilmiş, yamadan sonra yayımlanmıştır.
Donanım kurulumu
Kurulumda nRF52840 dongle, Saleae Logic 8 ve hava trafiğini yakalamak için btmon. İlk eşleştirme paketleri Ubertooth ile kaydedildi.
$ sudo btmon -w capture.btsnoop
# <-- bilekliği aç, telefon ile eşle -->
$ wireshark capture.btsnoop -Y "btatt"
Trafiği yakalamak
İlk 200 paket yalnızca advertisement; 0x180A numaralı Device Information service okunuyor ve seri numarası açık metin. Bu seri numarası daha sonra eşleştirme aşamasında “shared secret” gibi kullanılıyor — ki bu kriptografik olarak hatalı bir varsayım.
Sniffer’ı advertising kanallarına (37/38/39) sabitleyip bağlantı kurulduğu anda data kanallarına atlama (hop) parametrelerini yakalamak kritik. nRF Sniffer bunu otomatik yapıyor; aksi halde her bağlantıda farklı kanal haritası çıkıyor.
GATT haritalama
Bağlantı sonrası tüm servis ve karakteristikleri çıkarmak için gatttool / bleak ile primary service taraması yaptım. İlginç olan, üretici-tanımlı (vendor-specific) 0xFFE0 servisi: komutlar bu servisin 0xFFE1 karakteristiğine yazılıyor.
$ gatttool -b AA:BB:CC:DD:EE:FF --primary
# 0xffe0 vendor cmd service
# 0xffe1 write-without-response ← komut kanalı
# 0x180a device info (seri no açık)
0xFFE1 karakteristiğinin write-without-response izniyle açık olması, kimlik doğrulama olmadan komut yazılabileceğine dair ilk güçlü işaret.
Eşleştirme akışı
Cihaz “Just Works” eşleştirme kullanıyor — MITM korumasız. Beklenen savunma, uygulama katmanındaki komut imzalama olmalıydı. Ancak imza anahtarı, 0x180A’dan okunan seri numarasının SHA-1 özetinin ilk 16 baytı. Yani anahtar, herkesin okuyabildiği bir değerden türüyor.
// kök sebep — Gizli olması gereken anahtar (shared secret), açık yayınlanan bir tanımlayıcıdan deterministik üretiliyor. Saldırgan seri numarasını okur → anahtarı yeniden üretir → geçerli komut imzalar.
Yetkisiz komut
Anahtarı türetip 0xFFE1’e imzalı bir “fabrika sıfırlama” komutu yazdığımda cihaz, eşleşmiş telefon olmadan komutu kabul etti. Replay bile gerekmedi — taze, geçerli bir paket ürettim.
$ python3 forge_cmd.py --serial 04A1F9 --cmd factory_reset
[+] key = sha1(serial)[:16] = 8c9a4f1d...
[+] write 0xffe1 ← a1 04 ff 02 8c9a...
[+] device ACK · reset in 3s
Sonuç & sorumlu açıklama
Açık, kriptografik anahtar yönetimi hatası: gizli bir değer, açık bir tanımlayıcıdan türetilemez. Düzeltme, eşleştirme sırasında üretilen rastgele bir oturum anahtarı (LTK) ve uygulama katmanında nonce’lu komut imzalama.
Üreticiye 2026-01-18’de bildirildi, 2026-04-10’da firmware yaması yayınlandı, bu yazı 90 gün penceresi sonunda yayımlandı. CVE talep edildi, henüz atanmadı.
Footnotes
-
Türetme şeması basitleştirildi; gerçek cihazda tuz (salt) sabit ve firmware’e gömülü. ↩
// yazının sonunda
Yukarıda anlatılan tekniği donanım kurmadan kendin denemek istersen canlı simülatörü aç →