Akıllı ev cihazı hackleme (2024)
(jmswrnr.com)- Üreticinin uygulamasına ve bulutuna bağlı ESP32 tabanlı bir hava temizleme cihazını Home Assistant üzerinden doğrudan kontrol etmek için uzaktan kontrol yolu tersine mühendislikle incelenip yerel bir sunucuyla değiştirildi
- Uygulama analizi, DNS atlatma ve Wireshark yakalamalarıyla cihazın
smartdeviceep.---.com:41014adresine UDP paketleri gönderdiği ve standart DTLS yerine özel bir protokol kullandığı doğrulandı - UART bağlantısı ve 4 MB flash dökümü aracılığıyla
dev_key.key, sertifikalar, sunucu ayarları ve WiFi ayarları elde edildi; Ghidra ve esp32knife ile firmware yapısı analiz edildi - Paketler 13 baytlık başlık ve sondaki 2 baytlık CRC-16, ECDH/HKDF anahtar üretimi,
AES-128-CBCve MessagePack serileştirmesini birleştiriyordu; firmware yamasıyla paylaşılan sır seri günlüğe yazdırılarak şifre çözme başarıldı - Nihai kurulum bir MITM proxy, yerel sunucu ve Mosquitto tabanlı MQTT köprüsünden oluştu; Home Assistant’ın MQTT Fan entegrasyonuyla güç ve fan hızı birkaç hafta boyunca kararlı şekilde kontrol edildi
Buluta bağımlı hava temizleme cihazını yerel kontrole dönüştürme
- Amaç, yalnızca üreticinin mobil uygulamasına ve bulut hesabına bağlanan hava temizleme cihazını Home Assistant üzerinden kontrol etmekti
- Telefonda Bluetooth, WiFi ve 5G açılıp kapatılarak yapılan kontrolde, uygulamanın cihazı yerel Bluetooth veya WiFi üzerinden değil, yalnızca internet bağlantısı üzerinden kontrol ettiği görüldü
- Cihaz ile bulut sunucusu arasında bir yerde fan hızı gibi kontrol değerleri gidip geldiğinden, ağ bölümü temel saldırı noktası hâline geldi
- Trafiği araya girip yakalayarak ve değerleri değiştirerek cihaz kontrol edilebilir
- Sunucu yanıtları emüle edilirse internet ve üretici bulutu olmadan da çalıştırılabilir
- Tersine mühendislik içeriği eğitim amaçlıdır; ürüne özgü hassas bilgiler olan özel anahtarlar, alan adları ve API uç noktaları bulanıklaştırılmış veya silinmiştir
- Cihazda değişiklik yapmak garantiyi geçersiz kılabilir veya cihazda kalıcı hasara yol açabilir
Uygulama analizi ve UDP trafiği yakalama
- Android uygulamasının
.apkdosyası çıkarıldı;classes.dex, dex2jar ve jd-gui ile açılarak içeriği incelendi MainActivity.classiçinde uygulamanın React Native tabanlı olduğu doğrulandı;assets/index.android.bundleiçinde güvenli WebSocket bağlantısı bulundu- Örnek kodda
wss://smartdeviceapi.---.combağlantısı yer alıyordu
- Örnek kodda
- Pi-hole’un DNS sorgusu görüntüleme özelliğiyle cihazın bağlandığı bulut sunucusu alan adı belirlendi
- Pi-hole’un
Local DNSözelliğiyle ilgili alan adı yerel iş istasyonu192.168.0.10adresine yönlendirildi ve Wireshark üzerinde cihaz IP’si192.168.0.61trafiği filtrelendi - Cihaz, iş istasyonunun
41014portuna UDP paketleri gönderiyordu
Röle kurulumu ve özel protokole dair ipuçları
- Yerel DNS bulut alan adını iş istasyonuna çözdüğü için gerçek sunucu IP’si Cloudflare DNS resolver
1.1.1.1üzerinden sorgulandı - node-udp-forwarder kullanılarak iş istasyonunun cihaz ile bulut sunucusu arasında UDP rölesi rolü üstlenmesi sağlandı
- Açılıştaki ilk paket ve sunucu yanıtı yakalandı, ancak okunabilir karakter dizisi olmadan rastgele baytlar gibi göründüğü için şifreleme olasılığı vardı
- Wireshark paketi DTLS olarak tanımadı; DTLS spesifikasyonundaki başlık biçimi de yakalanan paketlerden farklıydı
- Standart bir protokol olmadığı göründüğünden paket yapısı ve şifreleme yönteminin doğrudan tersine mühendislikle incelenmesi gerekti
ESP32 sökümü ve seri erişim
- Cihaz söküldüğünde ana PCB, fan bağlantı portu ve ön kontrol paneli şerit kablosu görüldü
- Ana kontrolcü
ESP32-WROOM-32Dolarak işaretlenmişti ve WiFi ile Bluetooth özelliklerine sahip ESP32 ailesinden bir mikrodenetleyiciydi - ESP32 tersine mühendisliğiyle ilgili materyaller için ESP32-reversing deposundan yararlanıldı
- ESP32 veri sayfasında
TXD0veRXD0pinleri doğrulandı; PCB’deki hata ayıklama pin deliklerine bağlı izler takip edilerek seri bağlantı noktası bulundu - Flipper Zero’nun
USB-UART Bridgeözelliğiyle UART bağlantısı kuruldu- Flipper Zero
TX, ESP32RXpinine bağlandı - Flipper Zero
RX, ESP32TXpinine bağlandı GND,GNDpinine bağlandı
- Flipper Zero
- Putty’de
COM7,115200hızında bağlanıldığında açılış günlükleri çıktı
Açılış günlüklerinde ortaya çıkan dosyalar ve sunucu ayarları
- Seri günlükler ESP32’nin 2 CPU çekirdeğine, WiFi/BT/BLE’ye ve 4 MB harici flash’a sahip bir çip olduğunu yazdırdı
- Uygulama
factorybölümünden çalışıyordu - FAT dosya sistemi bağlandı;
122 KiBtoplam alan ve0 KiBkullanılabilir alan gösterildi - Uygulama şu dosyaları okuyordu
serialdev_key.keySmartDevice-root-ca.crtSmartDevice-signer-ca.crtserver_config
- Sunucu ayarlarında
smartdeviceep.---.com:41014yer alıyordu
Flash dökümü ve bölüm yapısı
- ESP32’yi
Download Bootmodunda başlatmak içinIO0piniGNDpinine bağlıyken cihaza güç verildi - esptool kullanılarak 4 MB flash’ın tamamının dökümü alındı
- Komut:
esptool -p COM7 -b 115200 read_flash 0 0x400000 flash.bin
- Komut:
- Döküm birkaç kez alınarak okumanın doğru olduğu doğrulandı ve sorun çıkarsa yeniden flash’lanabilmesi için yedeklendi
- Döküm esp32knife ile analiz edilerek
partitions.csvelde edildi - Bölüm yapısında şu öğeler vardı
nvs: 16K anahtar-değer deposuotadata: 8K OTA verisiphy_init: 4K PHY verisifactory: 768K uygulama bölümüota_0,ota_1: her biri 768K OTA uygulama bölümüstorage: 1M FAT veri bölümü
- Okurdan gelen bir bilgiye göre bu flash dökümü, flash şifreleme etkin olsaydı korunabilirdi; ancak bu cihazda etkin değildi
Depolamada bulunan anahtarlar ve sertifikalar
nvsbölümünün en güncel durumunda WiFi SSID’si ve parolası vardı; geçmiş günlüklerinde daha önce kullanılan WiFi kimlik bilgileri de görünüyordu- FAT
storagebölümü, OSFMount ile sanal disk gibi bağlanarak incelendi - Depolamada şu dosyalar vardı
dev_infodev_key.keyserialserver_configSmartDevice-root-ca.crtSmartDevice-signer-ca.crtwifi_config
dev_key.key,-----BEGIN EC PRIVATE KEY-----ile başlayan bir Elliptic Curve özel anahtarıydı veopenssl ec -in dev_key.key -text -nooutile doğrulandı- İki
.crtdosyası-----BEGIN CERTIFICATE-----ile başlayan sertifikalardı veopenssl x509ile doğrulandı - Sertifikalar ve cihaz anahtarı cihazda saklandığı için UDP paket verilerinin şifrelenmesinde kullanılıyor olma olasılığı arttı
Ghidra analiz ortamının kurulumu
- Çalışan
factorybölüm imajı Ghidra CodeBrowser’da açılıp analiz edildi - ESP32, Xtensa komut kümesini kullandığı için
Tensilica Xtensa 32-bit little-endiandili seçildi - Ham bölüm imajı sanal bellek eşlemesini doğru yansıtmadığından, esp32knife ile
part.3.factory.elfoluşturulup yeniden içe aktarıldı RTC_DATAsegmentini desteklemek için esp32knife üzerinde yapılan değişikliğin commit’i de yayımlandı- SVD-Loader-Ghidra ile ESP32 çevre birimi yapısı ve bellek haritası yüklendi
- Ghidra’nın
SymbolImportScriptaracıyla ESP32 ROM işlev etiketleri içe aktarılarakprintfgibi yaygın ROM işlevlerinin kolayca tanımlanması sağlandı
Dizelerden bulunan şifreleme ipuçları
- Ghidra’daki
Defined Stringsiçinde seri günlükte görülen dize ve çevresindeki dizeler izlendi - Çevredeki dizelerde şu ipuçları vardı
Message CRC errorSeed ErrorPRNG failECDH setup failedmbedtls_ecdh_gen_public failedmbedtls_ecdh_compute_shared failedMBED HKDF failedWrite ECC conn packet
- mbedtls, kriptografik ilkel işlevleri, X509 sertifika işlemlerini, SSL/TLS ve DTLS’yi uygulayan açık kaynaklı bir kütüphanedir
- ECDH ve HKDF işlevlerinin doğrudan kullanılması, DTLS kullanılmaması dikkate alındığında, anahtar değişimi ve anahtar türetmenin özel bir protokol içinde uygulandığı analiz edildi
ECC conn packetdizesi, ilk bağlantı paketinin ECDH anahtar değişimi süreciyle ilişkili olduğunu gösterdi
Kontrol paneli bağımlılığını kaldıran firmware yaması
- PCB’yi fan ve kontrol paneline bağlı tutarak analiz yapmak zor olduğundan kontrol paneli çıkarıldı, ancak açılış sırasında
No Cap device found!günlüğüyle birlikte panic oluştu No Cap device found!dizesinin çevresindeki işlevCapSense Initçıktısı verdiği için bunun ön panelin kapasitif giriş başlatma mantığı olduğu değerlendirildi- Ghidra’da ilgili işleve
InitCapSense, onu çağıran servise iseStartCapSenseServiceadı verildi StartCapSenseServiceçağrı komutunopile değiştirilerek kontrol paneli servisinin başlatılması kaldırıldı- Ham
part.3.factoryimajındaki baytlar değiştirilip0x10000ofsetine yeniden flashlandı, ancak ESP32 imaj checksum hatası nedeniyle açılmadı - esptool’un iç mantığı temel alınarak uygulama bölümü checksum’ını düzelten bir betik eklendi
- Checksum’ı onarılan imaj flashlanınca cihaz kontrol paneli olmadan da normal çalıştı ve firmware değişikliği başarılı oldu
Paket başlığı ve CRC yapısı
- Birden fazla açılışta paketler karşılaştırıldığında ilk 13 baytın benzer, geri kalanının ise şifrelenmiş gibi göründüğü anlaşıldı
- Paket başlığı biçimi şöyleydi
55: protokolü tanımlayan magic byte00 31: paket uzunluğu02: mesaj tanımlayıcı01 23 45 67 89 AB CD EF FF: 9 baytlık cihaz seri numarası
- Mesaj ID deseni şöyleydi
0x02: akıllı cihazın ilk gönderdiği paket0x82: bulut sunucusunun ilk gönderdiği yanıt0x01: akıllı cihazın daha sonra gönderdiği paket0x81: sunucunun daha sonra gönderdiği yanıt
- Üst bit, istemci isteği ile sunucu yanıtını ayırıyor; alt bit ise ilk değişim ile sonraki paketleri ayırıyor
Message CRC errordizesine referans veren işlev izlenerek CRC doğrulama mantığı doğrulandı- Son 2 bayt, paketin geri kalanının tamamı için CRC-16 checksum’ıydı
- Polinom
0x1021 - Başlangıç değeri
0xFFFF - Birden fazla yakalanmış pakette aynı yöntemle doğrulandı
- Polinom
ECDH/HKDF anahtar üretim akışı
- İlk anahtar değişimi gibi görünen pakette, başlıktaki 13 bayt ve CRC’deki 2 bayt çıkarıldığında veri 32 bayttı; bu da 256 bitlik açık anahtar boyutuyla eşleşiyordu
- İstemci isteğinin başında
00 01bulunuyordu ve bu değer her açılışta değişmediği için bir veri tanımlayıcı gibi ele alındı - Ghidra’da hata dizeleri izlenerek anahtar üretim işlevi bulundu ve mbedtls kaynak koduyla karşılaştırılarak sözde kod düzeyinde özetlendi
- Anahtar üretim işlevi şu işlemleri yapıyordu
mbedtls_ecdh_gen_publicile ECDH anahtar çifti oluşturur- Oluşturulan anahtarın bellekteki başka bir anahtarla üzerine yazıldığı bir yapı görülür
- Başka bir açık anahtar yükler
mbedtls_ecdh_compute_sharedile paylaşılan sırrı hesaplarmbedtls_ctr_drbg_randomile 32 bayt rastgele değer üretirmbedtls_hkdfile nihai anahtarı türetir
- HKDF ayarları şöyleydi
- Hash:
SHA-256 salt: ECDH paylaşılan sırrıinput: cihazın ürettiği 32 baytlık rastgele değerinfo: 9 baytlık cihaz seri numarası- Çıkış anahtarı boyutu:
0x10, yani 16 bayt
- Hash:
- Çağıran işlev,
00 01sonuna 32 baytlık rastgele değeri ekleyerek0x22bayt gönderiyordu; bu da yakalanan ilk anahtar değişimi paketinin biçimiyle uyuşuyordu
Paylaşılan sırrın çıktılanması ve AES ile şifre çözme
- Nihai şifre çözme anahtarını hesaplamak için ECDH paylaşılan sırrı gerekiyordu
- JTAG hata ayıklama yerine, önceden devre dışı bırakılmış CapSense mantığının bulunduğu konuma özel bir işlev yazılarak firmware paylaşılan sırrı seri hatta yazdıracak şekilde yamalandı
GenerateNetworkKeyiçinde paylaşılan sır oluşturulduktan hemen sonra işlev çağrısı eklendi ve register’daki anahtar işaretçisi kullanılarak 32 bayt yazdırıldı- Açılışta
Write ECC conn packetsonrasında paylaşılan sır onaltılık olarak çıktılanıyordu ve birkaç kez yeniden başlatmaya rağmen değer değişmiyordu - HKDF çıkış anahtarı da ayrı bir yamayla doğrulandı ve yakalanan paketlerde aynı anahtar üretim mantığı yeniden üretilebildi
- Şifreleme işlevinin içinde
63 7C 77 7B F2 6B 6F C5ile başlayan statik bir tablo bulundu ve bunun mbedtls’in AES Forward S-Box tablosuyla eşleştiği görüldü - Nihai şifreleme yöntemi AES-128-CBC idi ve paket içindeki 16 baytlık rastgele değer IV olarak kullanılıyordu
- Şifresi çözülen paketlerde
mirror_data_get,FAN_SPEED,BOOST,FILTER1,FILTER2gibi okunabilir değerler doğrulandı
MITM proxy uygulaması
- Cihaz özel anahtarı ve anahtar türetme mantığı elde edilmişti; gerekli dinamik veri ağda görünür olduğundan firmware yaması olmadan MITM proxy yazılabildi
- Node.js betiği yerel UDP soketi ve bulut sunucusu için UDP soketi oluşturup paketleri iki yönde iletir
- Akıllı cihazdan alınan paketler günlüğe yazıldıktan sonra bulut sunucusuna gönderilir; bulut sunucusundan alınan paketler de günlüğe yazıldıktan sonra akıllı cihaza gönderilir
messageIddeğeri2olan paket anahtar değişimi paketi olarak kabul edilir ve içindeki rastgele değer kullanılarak sonraki paketlerin AES anahtarı hesaplanır- Mobil uygulamayla cihaz kontrol edilirken MITM günlükleri biriktirilerek yerel sunucu uygulaması için gereken istek ve yanıt biçimleri doğrulandı
MessagePack mesaj yapısı
- Şifresi çözülmüş veri hâlâ ikili bir serileştirme biçimindeydi
- İç veri başlığı, little-endian biçiminde bir ID ve uzunluk gibi görünüyordu
01 00: paket ID’si64 00: işlem ID’si29 00: serileştirilmiş veri uzunluğu
- Serileştirme biçiminin bir kısmını kendim tersine mühendislikle çözmüştüm; ancak kontrol edince bunun MessagePack olduğu anlaşıldı
msgpackrgibi bir uygulama kullanıldığında ikili veri kolayca JSON biçiminde açılabiliyordu- Tespit edilen başlıca mesajlar şunlardı
- Anahtar değişimi: cihaz, HKDF’de kullanılacak rastgele baytları sunucuya gönderir
mirror_data_get: açılış sırasında ilk durumu sunucudan alırconnect: mevcut firmware UUID’sini gönderir; sunucu da firmware, ayar, saat ve sunucu adresi bilgileriyle yanıt verirmirror_data: sunucu cihaz durumunu değiştirir ya da cihaz değişen durumunu sunucuya bildirirkeep_alive: cihaz RSSI, RTT, paket kaybı, bağlantı sayısı, çalışma süresi gibi durum bilgilerini periyodik olarak gönderir
MQTT köprüsü ve Home Assistant entegrasyonu
- Home Assistant ile özel sunucuyu bağlamak için MQTT kullanıldı
- Home Assistant’ta açık kaynak MQTT broker’ı Mosquitto eklentisi yapılandırıldı
- Bağlantı yapısı
Home Assistant↔MQTT Broker↔Custom Server↔Smart Deviceşeklindedir - Özel sunucu şu şekilde çalışır
- Cihaz
mirror_data_getile durum istediğinde MQTT broker’daki retained değeri kullanır veya varsayılan değerle yanıt verir - Home Assistant bir durum değiştirme komutunu MQTT topic’i olarak gönderdiğinde özel sunucu bunu cihaza iletir
- Cihaz durumu herhangi bir nedenle değiştiğinde cihazın
mirror_datapaketini MQTT broker’a publish eder ve retain eder
- Cihaz
- Durum için source of truth her zaman cihazdır
- Durum güncellemesi başarısız olursa MQTT broker’da güncellenmiş gibi gösterilmez
- Durum fiziksel kontrol panelinden değişse bile MQTT broker’a yansıtılır
- Hava temizleyiciyi fan cihazı olarak eşlemek için Home Assistant’ın MQTT Fan entegrasyonu kullanıldı
configuration.yamliçinde güç durumu topic’i, komut topic’i, fan hızı durumu topic’i, fan hızı komut topic’i ve1~4hız aralığı ayarlandı- Pi-hole yerel DNS, üreticinin bulut domain’ini özel sunucuya çözecek şekilde ayarlanarak yerel sunucunun cihazın sunucusu gibi davranması sağlandı
Güvenlik değerlendirmesi ve sonuçlar
- Üretici, DTLS gibi standart protokoller yerine kendi protokolünü uygulamıştı
- Her cihazda benzersiz bir özel anahtar olup olmadığı kesin değil; ancak her iki durumda da dezavantajlar var
- Tüm cihazlar aynı firmware özel anahtarını paylaşıyorsa tek bir cihazı tersine mühendislikle analiz etmek bile diğer cihazlara MITM saldırısı denemeyi mümkün kılar
- Her cihazda benzersiz bir özel anahtar varsa sunucunun seri numarası ile cihaz anahtarı eşlemesini tutması gerekir; bu verilerin kaybı durumunda sunucu cihaz iletişimine yanıt veremez hâle gelir
- Firmware’de statik bir özel anahtar bulunduğu için saldırgan tek bir firmware dökümünden anahtarı elde edip MITM saldırısı gerçekleştirebilir
- Uygulama güvenlik açısından tamamen kötü değil; saldırı için hâlâ fiziksel erişim gerekiyor
- Özel uygulama ağ iletişimini opak hâle getirmiş olsa da Security through obscurity, standart uygulamaları hedefleyen genel saldırıları bir süre engelleme düzeyine yakındır ve saldırgan için aşılabilir bir engeldir
- Nihai hedef olan Home Assistant entegrasyonu başarıldı ve hava temizleyici birkaç hafta boyunca sorunsuz çalıştı
- Ayrı bir hava monitöründe PM2.5 veya VOC değerleri çok yükselirse hava temizleyiciyi belirli bir süre boost moduna alan bir otomasyon da yapılandırıldı
Henüz yorum yok.