Peretasan Perangkat Smart Home (2024)
(jmswrnr.com)- Untuk mengendalikan langsung air purifier berbasis ESP32 yang terikat pada aplikasi dan cloud pabrikan dari Home Assistant, jalur kendali jarak jauhnya direkayasa balik lalu diganti dengan server lokal
- Melalui analisis aplikasi, bypass DNS, dan capture Wireshark, diketahui bahwa perangkat mengirim paket UDP ke
smartdeviceep.---.com:41014dan memakai protokol kustom, bukan DTLS standar - Lewat koneksi UART dan dump flash 4MB, diperoleh
dev_key.key, sertifikat, konfigurasi server, dan konfigurasi WiFi; struktur firmware dianalisis dengan Ghidra dan esp32knife - Paket menggabungkan header 13 byte dan CRC-16 2 byte terakhir, pembuatan kunci ECDH/HKDF,
AES-128-CBC, serta serialisasi MessagePack; dekripsi berhasil setelah patch firmware membuat shared secret dicetak ke log serial - Konfigurasi akhir terdiri dari proxy MITM, server lokal, dan bridge MQTT berbasis Mosquitto; daya dan kecepatan kipas berhasil dikendalikan secara stabil selama beberapa minggu melalui MQTT Fan di Home Assistant
Mengubah air purifier yang bergantung pada cloud menjadi kendali lokal
- Tujuannya adalah mengendalikan air purifier yang hanya terhubung ke aplikasi mobile dan akun cloud pabrikan dari Home Assistant
- Setelah memeriksa dengan men-toggle Bluetooth, WiFi, dan 5G pada ponsel, ditemukan bahwa aplikasi mengendalikan perangkat hanya melalui koneksi internet, bukan Bluetooth atau WiFi lokal
- Karena nilai kendali seperti kecepatan kipas dikirimkan di suatu titik antara perangkat dan server cloud, segmen jaringan menjadi titik serangan utama
- Jika traffic dicegat dan nilainya diubah, perangkat dapat dikendalikan
- Jika respons server diemulasikan, perangkat dapat dijalankan tanpa internet maupun cloud pabrikan
- Materi rekayasa balik ini untuk tujuan edukasi, dan informasi sensitif per produk seperti private key, domain, serta endpoint API telah diobfusikasi atau dihapus
- Modifikasi perangkat dapat membatalkan garansi atau merusak perangkat secara permanen
Analisis aplikasi dan capture traffic UDP
- Mengekstrak
.apkaplikasi Android, lalu membukanya dengan dex2jar dan jd-gui untuk melihat bagian dalamnya - Di
MainActivity.class, diketahui bahwa aplikasi berbasis React Native, dan koneksi WebSocket aman ditemukan diassets/index.android.bundle- Kode contoh memuat koneksi ke
wss://smartdeviceapi.---.com
- Kode contoh memuat koneksi ke
- Dengan fitur penelusuran kueri DNS di Pi-hole, domain server cloud yang diakses perangkat berhasil diidentifikasi
- Menggunakan fitur
Local DNSdi Pi-hole, domain tersebut diarahkan ke workstation lokal192.168.0.10, lalu traffic IP perangkat192.168.0.61difilter di Wireshark - Perangkat mengirim paket UDP ke port
41014di workstation
Konfigurasi relay dan petunjuk protokol kustom
- Karena DNS lokal dibuat agar domain cloud di-resolve ke workstation, IP server sebenarnya dicari melalui Cloudflare DNS resolver
1.1.1.1 - Menggunakan node-udp-forwarder, workstation dijadikan relay UDP antara perangkat dan server cloud
- Paket pertama saat boot dan respons server berhasil di-capture, tetapi tampak seperti byte acak tanpa string yang dapat dibaca, sehingga ada kemungkinan terenkripsi
- Wireshark tidak mengenali paket tersebut sebagai DTLS, dan format header pada spesifikasi DTLS juga berbeda dari paket yang di-capture
- Karena tampaknya bukan protokol standar, struktur paket dan metode enkripsinya harus direkayasa balik secara langsung
Membongkar ESP32 dan akses serial
- Setelah perangkat dibongkar, terlihat PCB utama, port koneksi kipas, dan kabel ribbon panel kontrol depan
- Kontroler utamanya bertanda
ESP32-WROOM-32D, yaitu mikrokontroler keluarga ESP32 dengan fungsi WiFi dan Bluetooth - Referensi terkait rekayasa balik ESP32 diambil dari repositori ESP32-reversing
- Dari datasheet ESP32, pin
TXD0danRXD0diidentifikasi, lalu titik koneksi serial ditemukan dengan mengikuti trace yang terhubung ke lubang pin debugging pada PCB - Koneksi UART disiapkan menggunakan
USB-UART Bridgepada Flipper Zero- Flipper Zero
TXdihubungkan ke ESP32RX - Flipper Zero
RXdihubungkan ke ESP32TX GNDdihubungkan keGND
- Flipper Zero
- Saat terhubung dari Putty pada
COM7dengan baud rate115200, log boot ditampilkan
File dan konfigurasi server yang terungkap dari log boot
- Log serial mencetak bahwa ESP32 adalah chip dengan 2 core CPU, WiFi/BT/BLE, dan flash eksternal 4MB
- Aplikasi berjalan dari partisi
factory - Sistem file FAT di-mount, dan ditampilkan total ruang
122 KiBdengan ruang tersedia0 KiB - Aplikasi membaca file berikut
serialdev_key.keySmartDevice-root-ca.crtSmartDevice-signer-ca.crtserver_config
- Konfigurasi server memuat
smartdeviceep.---.com:41014
Dump flash dan struktur partisi
- Untuk mem-boot ESP32 ke mode
Download Boot, perangkat dinyalakan sambil pinIO0dihubungkan keGND - Menggunakan esptool, seluruh flash 4MB di-dump
- Perintahnya adalah
esptool -p COM7 -b 115200 read_flash 0 0x400000 flash.bin
- Perintahnya adalah
- Dump dilakukan beberapa kali untuk memastikan pembacaan normal, dan dicadangkan agar dapat di-flash ulang jika terjadi masalah
- Dump dianalisis dengan esp32knife untuk memperoleh
partitions.csv - Struktur partisi mencakup item berikut
nvs: penyimpanan key-value 16Kotadata: data OTA 8Kphy_init: data PHY 4Kfactory: partisi aplikasi 768Kota_0,ota_1: masing-masing partisi aplikasi OTA 768Kstorage: partisi data FAT 1M
- Menurut laporan pembaca, dump flash ini bisa saja terlindungi jika enkripsi flash diaktifkan, tetapi pada perangkat ini fitur tersebut tidak aktif
Kunci dan sertifikat yang ditemukan di storage
- Status terbaru partisi
nvsberisi SSID dan kata sandi WiFi, dan log riwayat juga memperlihatkan kredensial WiFi yang pernah digunakan sebelumnya - Partisi FAT
storagediperiksa dengan me-mount-nya sebagai disk virtual menggunakan OSFMount - Storage berisi file berikut
dev_infodev_key.keyserialserver_configSmartDevice-root-ca.crtSmartDevice-signer-ca.crtwifi_config
dev_key.keyadalah private key Elliptic Curve yang diawali dengan-----BEGIN EC PRIVATE KEY-----, dan diverifikasi denganopenssl ec -in dev_key.key -text -noout- Dua file
.crtadalah sertifikat yang diawali dengan-----BEGIN CERTIFICATE-----, dan diverifikasi denganopenssl x509 - Karena sertifikat dan kunci perangkat tersimpan di perangkat, besar kemungkinan keduanya digunakan untuk mengenkripsi data paket UDP
Menyiapkan lingkungan analisis Ghidra
- Image partisi
factoryyang sedang berjalan dibuka dan dianalisis di CodeBrowser Ghidra - Karena ESP32 menggunakan set instruksi Xtensa, bahasa
Tensilica Xtensa 32-bit little-endiandipilih - Image partisi mentah tidak dapat merefleksikan pemetaan memori virtual dengan benar, sehingga
part.3.factory.elfdibuat dengan esp32knife lalu diimpor kembali - Commit yang memodifikasi esp32knife agar mendukung segmen
RTC_DATAjuga dipublikasikan - Struktur periferal dan peta memori ESP32 dimuat dengan SVD-Loader-Ghidra
- Label fungsi ROM ESP32 diimpor dengan
SymbolImportScriptmilik Ghidra agar fungsi ROM umum sepertiprintflebih mudah diidentifikasi
Petunjuk enkripsi yang ditemukan dari string
- Di
Defined StringsGhidra, string yang terlihat di log serial dan string di sekitarnya ditelusuri - Di antara string di sekitarnya terdapat petunjuk berikut
Message CRC errorSeed ErrorPRNG failECDH setup failedmbedtls_ecdh_gen_public failedmbedtls_ecdh_compute_shared failedMBED HKDF failedWrite ECC conn packet
- mbedtls adalah library open source yang mengimplementasikan primitif kriptografi, manipulasi sertifikat X509, SSL/TLS, dan DTLS
- Dari fakta bahwa fungsi ECDH dan HKDF digunakan langsung dan bukan DTLS, dianalisis bahwa pertukaran kunci dan derivasi kunci diimplementasikan di dalam protokol buatan sendiri
- String
ECC conn packetmenunjukkan bahwa paket koneksi awal berkaitan dengan proses pertukaran kunci ECDH
Patch firmware untuk menghapus dependensi panel kontrol
- Analisis sulit dilakukan saat PCB masih terhubung ke kipas dan panel kontrol, sehingga panel kontrol dilepas, tetapi saat boot terjadi panic disertai log
No Cap device found! - Fungsi di sekitar string
No Cap device found!mencetakCapSense Init, sehingga dinilai sebagai logika inisialisasi input kapasitif pada panel depan - Di Ghidra, fungsi tersebut diberi nama
InitCapSense, dan layanan yang memanggilnya diberi namaStartCapSenseService - Instruksi pemanggilan
StartCapSenseServicediubah menjadinopuntuk menghapus dimulainya layanan panel kontrol - Byte pada image mentah
part.3.factorydimodifikasi dan di-flash kembali ke offset0x10000, tetapi perangkat tidak bisa boot karena error checksum image ESP32 - Berdasarkan logika internal esptool, skrip untuk memperbaiki checksum partisi aplikasi ditambahkan
- Setelah image yang checksumnya dipulihkan di-flash, perangkat berjalan normal tanpa panel kontrol, dan modifikasi firmware berhasil
Struktur header paket dan CRC
- Setelah membandingkan paket dari beberapa kali boot, 13 byte pertama tampak serupa dan sisanya terlihat seperti terenkripsi
- Format header paket adalah sebagai berikut
55: byte magic untuk identifikasi protokol00 31: panjang paket02: pengidentifikasi pesan01 23 45 67 89 AB CD EF FF: serial perangkat 9 byte
- Pola ID pesan adalah sebagai berikut
0x02: paket pertama yang dikirim perangkat pintar0x82: respons pertama yang dikirim server cloud0x01: paket berikutnya yang dikirim perangkat pintar0x81: respons berikutnya yang dikirim server
- Bit atas membedakan request klien dan respons server, sedangkan bit bawah membedakan pertukaran awal dan paket berikutnya
- Dengan menelusuri fungsi yang mereferensikan string
Message CRC error, logika verifikasi CRC dikonfirmasi - 2 byte terakhir adalah checksum CRC-16 untuk seluruh sisa paket
- Polinomialnya
0x1021 - Nilai awalnya
0xFFFF - Diverifikasi dengan cara yang sama pada beberapa paket hasil capture
- Polinomialnya
Alur pembuatan kunci ECDH/HKDF
- Pada paket yang tampak sebagai pertukaran kunci awal, data setelah header 13 byte dan CRC 2 byte berukuran 32 byte, sesuai dengan ukuran kunci publik 256-bit
- Pada request klien, terdapat
00 01di depan, dan nilainya tidak berubah setiap boot, sehingga diperlakukan seperti deskriptor data - Di Ghidra, fungsi pembuatan kunci ditemukan dengan menelusuri string error, lalu dirangkum pada tingkat pseudocode dengan membandingkannya dengan source mbedtls
- Fungsi pembuatan kunci melakukan operasi berikut
- Membuat pasangan kunci ECDH dengan
mbedtls_ecdh_gen_public - Terlihat pola menimpa kunci yang dibuat dengan kunci lain di memori
- Memuat kunci publik lain
- Menghitung shared secret dengan
mbedtls_ecdh_compute_shared - Membuat nilai acak 32 byte dengan
mbedtls_ctr_drbg_random - Menderivasi kunci akhir dengan
mbedtls_hkdf
- Membuat pasangan kunci ECDH dengan
- Pengaturan HKDF adalah sebagai berikut
- Hash:
SHA-256 salt: shared secret ECDHinput: nilai acak 32 byte yang dibuat perangkatinfo: serial perangkat 9 byte- Ukuran kunci output:
0x10, yaitu 16 byte
- Hash:
- Fungsi pemanggil menambahkan nilai acak 32 byte setelah
00 01dan mengirim0x22byte, yang cocok dengan format paket pertukaran kunci awal yang dicapture
Output shared secret dan dekripsi AES
- Untuk menghitung kunci dekripsi akhir, shared secret ECDH diperlukan
- Alih-alih debugging JTAG, firmware dipatch dengan menimpa lokasi logika CapSense yang sudah dinonaktifkan dengan fungsi kustom agar shared secret dicetak lewat serial
- Pemanggilan fungsi disisipkan tepat setelah shared secret dibuat di
GenerateNetworkKey, lalu 32 byte dicetak menggunakan pointer kunci di register - Saat boot, shared secret tercetak dalam heksadesimal setelah
Write ECC conn packet, dan nilainya tidak berubah meski di-reboot beberapa kali - Kunci output HKDF juga dikonfirmasi lewat patch terpisah, dan logika pembuatan kunci yang sama dapat direproduksi dari paket hasil capture
- Di dalam fungsi enkripsi ditemukan tabel statis yang diawali
63 7C 77 7B F2 6B 6F C5, dan ini cocok dengan AES Forward S-Box milik mbedtls - Metode enkripsi akhirnya adalah AES-128-CBC, dan nilai acak 16 byte di dalam paket digunakan sebagai IV
- Pada paket yang didekripsi, nilai yang dapat dibaca seperti
mirror_data_get,FAN_SPEED,BOOST,FILTER1, danFILTER2terkonfirmasi
Implementasi proxy MITM
- Kunci privat perangkat dan logika derivasi kunci telah diperoleh, dan data dinamis yang diperlukan terekspos di jaringan, sehingga proxy MITM dapat ditulis tanpa patch firmware
- Skrip Node.js membuat socket UDP lokal dan socket UDP untuk server cloud, lalu meneruskan paket dua arah
- Paket yang diterima dari perangkat pintar dicatat ke log lalu dikirim ke server cloud, sedangkan paket yang diterima dari server cloud dicatat ke log lalu dikirim ke perangkat pintar
- Paket dengan
messageIdbernilai2dianggap sebagai paket pertukaran kunci, dan kunci AES untuk paket berikutnya dihitung menggunakan nilai acak di dalamnya - Saat mengoperasikan perangkat lewat aplikasi mobile, log MITM dikumpulkan untuk mengonfirmasi bentuk request dan respons yang diperlukan untuk implementasi server lokal
Struktur Pesan MessagePack
- Data yang telah didekripsi masih berupa format serialisasi biner
- Header data internal tampak seperti ID dan panjang dalam little-endian
01 00: ID paket64 00: ID transaksi29 00: panjang data serialisasi
- Format serialisasi sempat direkayasa balik sebagian secara manual, tetapi setelah diperiksa ternyata adalah MessagePack
- Dengan menggunakan implementasi seperti
msgpackr, data biner dapat dengan mudah diurai ke bentuk JSON - Pesan-pesan utama yang teridentifikasi adalah sebagai berikut
- Pertukaran kunci: perangkat mengirim byte acak yang akan digunakan untuk HKDF ke server
mirror_data_get: mengambil status awal dari server saat bootingconnect: mengirim UUID firmware saat ini, lalu server merespons dengan informasi firmware, konfigurasi, waktu, dan alamat servermirror_data: server mengubah status perangkat, atau perangkat melaporkan status yang berubah ke serverkeep_alive: perangkat mengirim status secara berkala seperti RSSI, RTT, packet drop, jumlah koneksi, uptime, dan sebagainya
Bridge MQTT dan Integrasi Home Assistant
- MQTT digunakan untuk menghubungkan Home Assistant dengan server kustom
- Di Home Assistant, add-on Mosquitto, broker MQTT open-source, dikonfigurasi
- Struktur koneksinya berbentuk
Home Assistant↔MQTT Broker↔Custom Server↔Smart Device - Server kustom bekerja dengan cara berikut
- Saat perangkat meminta status dengan
mirror_data_get, server merespons menggunakan nilai retained dari broker MQTT atau nilai default - Saat Home Assistant mengirim perintah perubahan status ke topik MQTT, server kustom meneruskannya ke perangkat
- Jika status perangkat berubah karena alasan apa pun, paket
mirror_datadari perangkat di-publish ke broker MQTT dan di-retain
- Saat perangkat meminta status dengan
- Source of truth untuk status selalu ada pada perangkat
- Jika pembaruan status gagal, broker MQTT tidak akan menampilkannya seolah-olah sudah diperbarui
- Jika status berubah melalui panel kontrol fisik, perubahan itu juga tercermin di broker MQTT
- Integrasi MQTT Fan di Home Assistant digunakan untuk memetakan air purifier sebagai perangkat kipas
- Di
configuration.yaml, dikonfigurasi topik status daya, topik perintah, topik status kecepatan kipas, topik perintah kecepatan kipas, serta rentang kecepatan1~4 - DNS lokal Pi-hole dikonfigurasi agar domain cloud milik produsen di-resolve ke server kustom, sehingga server lokal berperan sebagai server untuk perangkat
Evaluasi Keamanan dan Hasil
- Produsen mengimplementasikan protokol sendiri alih-alih protokol standar seperti DTLS
- Tidak jelas apakah setiap perangkat memiliki private key unik, tetapi dalam kedua kasus ada kelemahannya
- Jika semua perangkat berbagi private key firmware yang sama, hanya dengan merekayasa balik satu perangkat saja serangan MITM dapat dicoba terhadap perangkat lain
- Jika setiap perangkat memiliki private key unik, server harus menyimpan pemetaan antara nomor seri dan kunci perangkat, dan jika data tersebut hilang, server tidak akan bisa merespons komunikasi perangkat
- Karena firmware berisi private key statis, penyerang dapat memperoleh kunci dari satu dump firmware dan melakukan serangan MITM
- Implementasinya tidak sepenuhnya buruk dari sudut pandang keamanan, dan serangan masih memerlukan akses fisik
- Implementasi buatan sendiri membuat komunikasi jaringan menjadi tidak transparan, tetapi security through obscurity lebih mirip sekadar menahan sementara serangan umum yang menargetkan implementasi standar, dan bagi penyerang itu adalah hambatan yang bisa dilewati
- Tujuan akhir, yaitu integrasi Home Assistant, berhasil dicapai, dan air purifier berjalan tanpa masalah selama beberapa minggu
- Otomasi juga dikonfigurasi agar air purifier masuk mode boost selama periode tertentu ketika nilai PM2.5 atau VOC dari monitor udara terpisah menjadi terlalu tinggi
Belum ada komentar.