Reverse engineering protokołu ZigBee - co skrywa twoja żarówka
Sniffing ZigBee 3.0 za 120 PLN i co realnie da się zobaczyć w Philips Hue.
autor: Admin

Wstęp
ZigBee 3.0 to nadal najpopularniejszy protokół w smart home - Philips Hue, IKEA Trådfri, Aqara, większość zamków Yale. Z punktu widzenia bezpieczeństwa to też najczęściej najsłabsze ogniwo w domowej sieci, bo radio jest wszędzie, a aktualizacje firmware'u rzadkie.
W tym artykule pokażę, jak za 120 PLN (sonoff ZBDongle-E + ESP32 do analizy) złożyć stację sniffingu i co realnie da się zobaczyć w żarówce Philips Hue White v3.
Sprzęt
- Sonoff ZBDongle-E (EFR32MG21) - ok. 80 PLN, działa z firmware'em zigbee2mqtt sniffer lub Silabs'
Network Analyzer - ESP32-S3 DevKit - opcjonalnie, do skryptowania własnych pakietów przez
esp-zigbee-sdk1.4 - Linux z
wireshark4.4 i pluginemnRF Sniffer for 802.15.4
Krok 1: Flash sniffera
Pobieramy firmware z silabs/zigbee2mqtt-firmware i flashujemy przez mgmt-router Silabs:
sudo apt install python3-intelhex
python3 -m pip install pyusb pyserial
git clone https://github.com/Nerivec/silabs-firmware-builder
cd silabs-firmware-builder
python flash.py --port /dev/ttyACM0 --firmware ncp-uart-hw_sniffer.gbl
Po reboocie dongle pokazuje się jako interface 802.15.4. Wireshark widzi go przez extcap.
Krok 2: Co realnie jest szyfrowane
ZigBee używa AES-128-CCM* z dwoma poziomami kluczy:
- Trust Center Link Key (negocjowany w trakcie joinowania)
- Network Key (rotujący, dystrybuowany przez koordynator)
Słaby punkt: domyślny Trust Center Link Key (ZigBeeAlliance09, hex 5A 69 67 42 65 65 41 6C 6C 69 61 6E 63 65 30 39) jest publiczny i używany w 90% urządzeń konsumenckich podczas pierwszego parowania.
Jeśli nagrasz parowanie żarówki, możesz odszyfrować negocjację Network Key. W Wiresharku: Edit > Preferences > Protocols > ZigBee > Pre-configured Keys.
Krok 3: Co siedzi w komendach Philips Hue
Po odszyfrowaniu Network Key widać już application payload. Hue White v3 używa standardowych klastrów ZCL:
0x0006(On/Off)0x0008(Level Control)0x0300(Color Control)
ZCL Header: Frame Control=0x01 (cluster-specific)
Sequence=0x42
Command=0x04 (Move To Color Temperature)
Payload: Color Temperature=0x017c (380 mireds = ~2630K)
Transition Time=0x000a (1.0 s)
Co ciekawe - kolor lampki wycieka offline każdemu w zasięgu. Sąsiad > z dongla za 80 PLN wie, kiedy idziesz spać.
Krok 4: Replay attack
ZigBee używa frame counterów, więc literalny replay nie działa - ale jeśli przejmiesz Network Key, możesz wygenerować nowe pakiety z poprawnym counterem. Mały PoC w zigpy:
import asyncio
from zigpy_znp.zigbee.application import ControllerApplication
from zigpy.zcl.clusters.general import OnOff
async def toggle(target_ieee):
app = await ControllerApplication.new(config={"device": {"path": "/dev/ttyUSB0"}})
device = app.get_device(ieee=target_ieee)
cluster = device.endpoints[1].in_clusters[OnOff.cluster_id]
await cluster.command(OnOff.commands_by_name["toggle"].id)
asyncio.run(toggle(target_ieee="00:17:88:01:02:03:04:05"))
Krok 5: Co z tym zrobić jako użytkownik
- Zmień Trust Center Link Key - Home Assistant + zigbee2mqtt pozwala na generowanie losowego klucza per-sieć (
network_key: GENERATE) - Aktualizuj firmware koordynatora - wersje od 2024 wymuszają install codes dla nowych urządzeń (Hue od v2, Aqara od T1)
- Segreguj IoT - osobny VLAN, osobny SSID, brak dostępu do LAN-u
Podsumowanie
ZigBee jest bezpieczne na tyle, na ile bezpiecznie skonfigurujesz swoją sieć. Domyślne ustawienia z pudełka - szczególnie publiczny TCLK - to prezent dla każdego z dongle'm za 80 PLN. Dobra wiadomość: 15 minut w HA + zigbee2mqtt zamyka większość wektorów.
W następnej części pokażę, jak ten sam setup wykorzystać do fuzzingu implementacji ZCL - i czego nauczyło mnie wycelowanie tego w komercyjny zamek do drzwi.