offensive-z-wave

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Z-Wave Attacks

Z-Wave 攻击

Z-Wave runs in the 800/900 MHz ISM band (US: 908 MHz, EU: 868 MHz). Older networks used the S0 security scheme with a fixed-derivation network key — long-known to be flawed. S2 (mandatory for Z-Wave Plus v2 since 2017) uses ECDH commissioning and is significantly stronger.
Z-Wave 运行在 800/900 MHz ISM 频段(美国:908 MHz,欧洲:868 MHz)。较旧的网络使用 S0 安全方案,其网络密钥采用固定方式派生——这一缺陷早已广为人知。S2(自 2017 年起在 Z-Wave Plus v2 中成为强制要求)采用 ECDH 入网,安全性显著更高。

Quick Workflow

快速工作流

  1. Identify region (US 908 MHz / EU 868 MHz) — adapter frequency must match
  2. Sniff inclusion (commissioning) traffic — that's where keys are exchanged
  3. Determine S0 vs S2 from frame format
  4. For S0: derive/replay; for S2: analyze ECDH and look for implementation flaws

  1. 确定地区(美国 908 MHz / 欧洲 868 MHz)——适配器频率必须匹配
  2. 嗅探入网(commissioning)流量——密钥正是在这一阶段交换
  3. 根据帧格式判断是 S0 还是 S2
  4. 对于 S0:派生/重放;对于 S2:分析 ECDH 并查找实现缺陷

Hardware

硬件

AdapterUse
Z-Force (legacy, hard to find)Original research tool
EZ-Wave (custom HackRF firmware)Modern, full transceiver
Aeotec Z-StickCommercial controller, useful as legitimate node
HackRF + open Z-Wave firmwareMulti-band SDR approach
RTL-SDR + ZniffMobile (passive only)Cheap sniffer
适配器用途
Z-Force(旧版,较难找到)原始研究工具
EZ-Wave(自定义 HackRF firmware)现代全能收发器
Aeotec Z-Stick商用控制器,可用作合法节点
HackRF + 开源 Z-Wave firmware多频段 SDR 方案
RTL-SDR + ZniffMobile(仅被动)低成本嗅探器

Sniffing

嗅探

bash
undefined
bash
undefined

EZ-Wave (HackRF firmware-based)

EZ-Wave (HackRF firmware-based)

git clone https://github.com/cureHsu/EZ-Wave ezwave-sniff -f 908.4MHz -o capture.pcap
git clone https://github.com/cureHsu/EZ-Wave ezwave-sniff -f 908.4MHz -o capture.pcap

Wireshark with the Z-Wave dissector parses captured frames

Wireshark with the Z-Wave dissector parses captured frames

wireshark capture.pcap

Look for the inclusion phase (controller adding new device) — that's where the network key is exchanged.
wireshark capture.pcap

关注 inclusion 阶段(控制器添加新设备)——网络密钥正是在这一阶段交换。

S0 Security Flaw

S0 安全缺陷

S0 derives the network key from a fixed all-zero PSK during the inclusion of the first device. That fixed material is well-known — any S0 network you sniff during inclusion can be decrypted offline.
S0 commissioning:
  1. New node joins → controller sends key with zero-PSK encryption
  2. Attacker sniffs commissioning frame → derives session key
  3. All future S0 traffic on that network is decryptable
If you can:
  • Trigger inclusion (factory-reset a node, or wait for legitimate inclusion)
  • Sniff during the ~2-second key-exchange window
You own the network key for that mesh.
S0 在第一个设备入网时,使用固定的全零 PSK 派生网络密钥。这段固定材料早已广为人知——任何在入网期间被你嗅探到的 S0 网络都可以离线解密。
S0 commissioning:
  1. New node joins → controller sends key with zero-PSK encryption
  2. Attacker sniffs commissioning frame → derives session key
  3. All future S0 traffic on that network is decryptable
如果你能够:
  • 触发 inclusion(将节点恢复出厂设置,或等待合法的 inclusion)
  • 在约 2 秒的密钥交换窗口内进行嗅探
那么你就拥有该 mesh 的网络密钥。

S2 (Z-Wave Plus / S2 Authenticated)

S2(Z-Wave Plus / S2 Authenticated)

S2 fixes S0 by using ECDH for commissioning:
  • Each device has a Curve25519 keypair
  • Inclusion uses DSK (Device Specific Key) verified out-of-band (sticker/QR)
  • Network key never traverses the air in plaintext
S2 attack surface is mostly implementation:
  • Inclusion-mode-always-open (controller misconfig)
  • Firmware bugs in S2 verification
  • Side-channel on ECDH on resource-constrained chips
  • DSK printed on a sticker → physical access yields it
S2 使用 ECDH 进行入网,从而修复了 S0:
  • 每个设备都有一对 Curve25519 密钥
  • inclusion 使用 DSK(Device Specific Key),并通过带外方式进行验证(贴纸/QR)
  • 网络密钥绝不会在空口以明文形式传输
S2 的攻击面主要在于实现缺陷:
  • Inclusion-mode-always-open(控制器配置错误)
  • S2 验证中的 firmware 缺陷
  • 资源受限芯片上的 ECDH 侧信道
  • DSK 印在贴纸上 → 可通过物理接触获取

Replay / Injection on Unauthenticated Nodes

未认证节点上的重放 / 注入

Many low-end Z-Wave devices (older sensors, basic switches) don't enforce S0 or S2 — they accept commands in cleartext.
python
undefined
许多低端 Z-Wave 设备(较旧的传感器、基础开关)并不强制执行 S0 或 S2——它们会接受明文形式的命令。
python
undefined

scapy-zwave (community fork) for crafted frames

scapy-zwave (community fork) for crafted frames

from scapy.contrib.zwave import * frame = ZWave(home_id=0x12345678)/ZWaveBasic(set_value=0xff) sendp(frame, iface='ezwave0')

This unlocks doors / switches lights / unarms sensors when the target lacks authentication.
from scapy.contrib.zwave import * frame = ZWave(home_id=0x12345678)/ZWaveBasic(set_value=0xff) sendp(frame, iface='ezwave0')

当目标缺少认证时,这可以打开门、开关灯或解除传感器警报。

Key Brute-Force

密钥暴力破解

For old test deployments using default home IDs / network keys:
bash
undefined
针对使用默认 home ID / 网络密钥的旧测试部署:
bash
undefined

Try default home IDs

Try default home IDs

for hid in 0x00000000 0x12345678 ...; do ezwave-test --home-id $hid --target-node 1 done

Hit rate on production is low; useful only for default-config IoT lab gear.
for hid in 0x00000000 0x12345678 ...; do ezwave-test --home-id $hid --target-node 1 done

在生产环境中的命中率很低;仅对采用默认配置的 IoT 实验设备有用。

Hub Pivots

Hub 横向突破

Z-Wave devices are typically controlled by a hub (SmartThings, Hubitat, Vera, Home Assistant, Z-Wave JS UI). The hub is a Linux device with the Z-Wave PSK in plaintext storage:
  • SmartThings Hub: previously cloud-only credentials; modern v3 stores network key locally
  • Home Assistant:
    ~/.homeassistant/zwave_js.json
    typically contains keys
  • Hubitat: web UI with default password on older versions
Compromise the hub → walk away with the Z-Wave PSK + every paired device's command authority. See
offensive-iot
for hub firmware extraction.
Z-Wave 设备通常由 hub 控制(SmartThings、Hubitat、Vera、Home Assistant、Z-Wave JS UI)。hub 是一台 Linux 设备,Z-Wave PSK 以明文形式存储:
  • SmartThings Hub:过去仅在云端保存凭据;现代 v3 会在本地存储网络密钥
  • Home Assistant:
    ~/.homeassistant/zwave_js.json
    通常包含密钥
  • Hubitat:旧版本提供带默认密码的 Web UI
攻陷 hub → 获取 Z-Wave PSK 以及每个已配对设备的命令权限。有关 hub firmware 提取,请参阅
offensive-iot
。

Engagement Cheatsheet

实战速查表

bash
undefined
bash
undefined

1. Identify region + frequency

1. Identify region + frequency

US: 908.4 MHz; EU: 868.4 MHz; CN: 868.4 MHz

US: 908.4 MHz; EU: 868.4 MHz; CN: 868.4 MHz

2. Sniff

2. Sniff\

ezwave-sniff -f 908.4MHz -o cap.pcap wireshark cap.pcap # filter zwave
ezwave-sniff -f 908.4MHz -o cap.pcap wireshark cap.pcap # filter zwave

3. Identify S0 vs S2 from frame format

3. Identify S0 vs S2 from frame format

4. For S0: capture inclusion → derive key → decrypt history + control devices

4. For S0: capture inclusion → derive key → decrypt history + control devices

5. For S2: focus on hub compromise / DSK theft / implementation bugs

5. For S2: focus on hub compromise / DSK theft / implementation bugs

6. Test unauthenticated cleartext devices with crafted frames

6. Test unauthenticated cleartext devices with crafted frames

undefined
undefined

Detection

检测

  • Most Z-Wave deployments have no IDS comparable to Wi-Fi/Zigbee monitoring
  • Hub may log unexpected commands but UI rarely surfaces these to users
  • Inclusion-mode-open is visible in hub UI but ignored by inattentive admins
  • 大多数 Z-Wave 部署都没有类似 Wi-Fi/Zigbee 监控的 IDS
  • Hub 可能会记录异常命令,但其 UI 很少向用户展示这些信息
  • Inclusion-mode-open 在 hub UI 中可见,但通常会被疏于管理的管理员忽略

Reporting

报告

  • Identify chipset / firmware revision per device (ZW0500 series, ZW7000 series)
  • Map S0 vs S2 per node — note any S0 left on a network with S2-capable nodes
  • Document hub compromise paths separately

  • 识别每个设备的芯片组 / firmware 修订版本(ZW0500 系列、ZW7000 系列)
  • 绘制每个节点的 S0 与 S2 分布——记录网络中仍残留的任何 S0 节点,包括与支持 S2 的节点共存的节点
  • 单独记录 hub 的失陷路径

Key References

主要参考资料