Zigbee/Z-Wave IoT Radio
Definition
Section titled “Definition”Zigbee and Z-Wave analysis covers the mesh-radio ecosystems that run smart buildings: Zigbee (IEEE 802.15.4 at 2.4 GHz, mesh via coordinators/routers, Zigbee 3.0’s security model) and Z-Wave (sub-GHz proprietary mesh, S2 security framework), plus the hub-centric architecture both imply — a coordinator/gateway that holds the network key, routers that forward, and battery-powered end devices that trust the mesh they joined. The analysis layers: frame-level literacy (802.15.4 MAC framing, Zigbee NWK/APS layers, sequence numbers and counters), key management (network keys distributed on join, link keys per pair, the trust-center role), and the attack families: passive sniffing of unencrypted networks, replay of command frames (the classic light-toggle), rejoin/key-extraction attacks against weak commissioning, Touchlink commissioning abuse (unauthenticated proximity commissioning), jamming denial, and hub-API attacks that bypass the radio entirely. Z-Wave’s S2 framework (2016+) raised the pairing bar (ECDH exchange, per-product keys [verify scheme details]) while the installed base of pre-S2 devices remains crackable — the same installed-base dynamic as every wireless generation before it.
Why It Matters
Section titled “Why It Matters”The mesh-radio estate is the invisible building network: lights, locks, sensors, thermostats, blinds — thousands of nodes per facility, meshing across rooms, all trusting a hub that procurement bought and nobody assessed. The attack consequences are physical and immediate: replayed command frames toggle locks and disable sensors, rejoin attacks extract network keys (and with them the whole mesh’s privacy), Touchlink abuse commissions attacker devices into the network from arm’s length, and hub-API weaknesses (the cloud/local API every hub ships) are the pragmatic shortcut around the radio entirely. For defenders, the estate’s invisibility is the core problem: mesh nodes don’t appear in NAC inventories, their firmware rarely patches, and their security posture varies by installation date — a 2015 hub and a 2024 hub on the same floor can differ by an entire security generation. The analysis discipline makes the estate legible: what’s actually on the air (frame census), what’s actually encrypted (NWK key presence), what’s actually replayable (command-frame freshness), and what the hub actually logs (the detection substrate). And the mesh topology adds the defensive twist unique to this layer: every router node forwards — so an attacker device commissioned into the mesh (Touchlink, stolen key) becomes a legitimate mesh participant with routing privileges, which is why commissioning security is the perimeter that matters, and why “who can join this mesh” is the question the whole module circles.
Detailed Explanation
Section titled “Detailed Explanation”The 802.15.4/Zigbee frame and key architecture:
802.15.4 MAC FRAME (what the sniffer sees) [Preamble+ SFD][FCS] MAC header: Frame Control | Seq No | DST PAN | DST Addr | SRC Addr Zigbee NWK layer: Frame Control | Dest | Src | Radius | Seq No | [key-protected payload] APS layer: endpoint/profile/cluster (ZCL frames)
TOPOLOGY & KEYS Coordinator (hub/trust center) -- holds NWK key | join: device asks; TC replies with NWK key | (in-the-clear on legacy, EAP-protected on | Zigbee 3.0 install-code join [verify]) Routers (mains-powered: bulbs, plugs) -- forward frames End devices (battery) -- sleep, poll parent
ATTACK FAMILIES sniffing: passive frames (plaintext if no NWK key) replay: retransmit command frames (seq reuse) rejoin attack: force device to rejoin attacker's network -> TC hands NWK key to attacker [verify] Touchlink: proximity commissioning w/o auth -> add attacker device as router jamming: 802.15.4 channel denial (loud, illegal) hub API: local/cloud API of the hub itselfThe frame census is the recon: passive capture (CC2531/Socket-class sniffers or SDR per WI6) catalogs PAN IDs, device addresses, frame types (beacon/data/command/ack), and — the decisive column — which payloads are encrypted (NWK security header present or not). Unencrypted Zigbee (legacy installs, default-config hubs) yields command frames in the clear, and replay is then a matter of retransmission. The sequence-number discipline is the freshness layer: 802.15.4 and Zigbee NWK both carry sequence numbers, and receivers should reject replays — implementations vary, which is why the replay test (transmit the captured toggle frame, watch the light) is the assessment’s empirical step, and why the freshness monitor (the tool below) is the defensive counterpart. The rejoin attack targets the join protocol: forcing a device to leave and rejoin through the attacker’s network lets the attacker play trust-center and receive the NWK key exchange — Zigbee 3.0’s install-code join (device-specific code authorizes the key delivery) is the fix, and its absence is the finding. The Touchlink abuse is proximity commissioning without authentication: an attacker within radio range commissions their own device into the network — a mesh router with forwarding privileges — after which the radio perimeter includes attacker infrastructure. The hub-API layer is the pragmatic path: local REST/Cloud APIs, default credentials, unauthenticated local endpoints — the radio is often harder than the hub’s own management plane, and assessments that skip the hub half-report the estate. Z-Wave’s S2 framework parallels the story: ECDH-based pairing with per-device keys (S2 Authenticated/Unauthenticated/Access Control classes [verify scheme]) fixed the pre-S2 zero-day-era weaknesses, and the installed base splits accordingly.
Common Techniques
Section titled “Common Techniques”| Technique | Target | What it does | Tooling | Notes |
|---|---|---|---|---|
| Passive frame census | Whole mesh | PANs, devices, encryption state | KillerBee, scapy Dot15d4 | Recon layer |
| Command replay | Lights/locks/relays | Retransmit captured commands | Sniffer Tx / custom | Freshness test |
| Rejoin attack | NWK key extraction | Force rejoin via attacker TC | KillerBee suite | Legacy joins [verify] |
| Touchlink abuse | Zigbee LL networks | Unauth proximity commissioning | Z3 tooling | Router-level implant |
| Install-code audit | Zigbee 3.0 joins | Verify key delivery protection | Config review | The modern fix |
| Z-Wave S2 check | Z-Wave estate | Pairing class per device | Zniffer-class [verify] | Installed-base split |
| Jamming (awareness) | 802.15.4 channels | Denial — illegal to deploy | Lab demo only | Detection, not attack |
| Hub API assessment | The hub itself | Local/cloud API, defaults | Standard web tooling | The pragmatic path |
| Mesh routing abuse | Comissioned implant | Attacker device forwards | Post-Touchlink | Perimeter implications |
| Counter/seq analysis | Freshness posture | Per-pair sequence discipline | This module’s tools | The defensive metric |
Full Working Code
Section titled “Full Working Code”zbreplay.py — a Zigbee capture analyzer and replay-checker: parses 802.15.4 captures (scapy’s Dot15d4 layer), builds the per-(src,dst) sequence-number state, detects sequence reuse (replay signatures already in the capture), classifies frame types, extracts PAN/device topology, and flags encrypted-vs-plaintext payload distribution. Dependency: scapy.
#!/usr/bin/env python3"""zbreplay.py — 802.15.4/Zigbee capture analyzer.Usage: python zbreplay.py capture.pcap [--json zb.json]Build capture: CC2531/zniffer-class sniffer or SDR (WI6).Deps: scapy."""import argparse, json, sysfrom collections import defaultdictfrom scapy.all import PcapReader, Dot15d4, Dot15d4Fcs, \ Dot15d4Data, Dot15d4Beacon, Dot15d4Cmd
FTYPE = {0: "beacon", 1: "data", 2: "ack", 3: "command"}
def analyze(path): frames = 0 pans = defaultdict(int) types = defaultdict(int) seq_state = defaultdict(lambda: { "seqs": [], "replays": 0, "count": 0}) topo = defaultdict(set) encrypted = {"on": 0, "off": 0} interesting = [] # data frames (replay candidates) with PcapReader(path) as reader: for pkt in reader: if Dot15d4 not in pkt: continue frames += 1 f = pkt[Dot15d4] ftype = f.fcf_frametype & 0x7 types[FTYPE.get(ftype, ftype)] += 1 src = f.src_addr dst = f.dest_addr pan = f.dest_panid if pan is not None: pans[hex(pan)] += 1 if src is not None and dst is not None: topo[src].add(dst) st = seq_state[(src, dst)] st["count"] += 1 seq = f.seqnum if seq in st["seqs"]: st["replays"] += 1 st["seqs"].append(seq) else: st["seqs"].append(seq) if len(st["seqs"]) > 256: st["seqs"] = st["seqs"][-128:] # security: FCF security-enabled bit (bit 3) sec = bool(f.fcf_security) if hasattr( f, "fcf_security") else False encrypted["on" if sec else "off"] += 1 if ftype == 1 and Dot15d4Data in pkt: interesting.append({ "src": src, "dst": dst, "seq": f.seqnum, "sec": sec, "payload_hex": bytes( pkt[Dot15d4Data].payload).hex()[:64]}) return {"frames": frames, "pans": dict(pans), "types": dict(types), "encrypted": encrypted, "replay_pairs": {f"{a}->{b}": v for (a, b), v in seq_state.items() if v["replays"]}, "topo_pairs": sum(len(v) for v in topo.values()), "data_frames": interesting[:50]}
def main(): ap = argparse.ArgumentParser() ap.add_argument("pcap") ap.add_argument("--json") args = ap.parse_args() s = analyze(args.pcap) print(f"== 802.15.4 census: {s['frames']} frames ==") print(f"PANs: {s['pans']}") print(f"frame types: {s['types']}") print(f"security-enabled frames: {s['encrypted']}") if s["replay_pairs"]: print("\n[!] sequence reuse (replay signatures " "already in capture):") for pair, v in list(s["replay_pairs"].items())[:8]: print(f" {pair}: {v['replays']} repeats " f"of {v['count']} frames") else: print("\n[+] no sequence reuse observed in capture") print(f"[i] data frames captured: " f"{len(s['data_frames'])} (replay candidates)") if args.json: json.dump(s, open(args.json, "w"), indent=2) print(f"[+] {args.json}")
if __name__ == "__main__": main()Code Walkthrough
Section titled “Code Walkthrough”- The frame-type decode (lines 33-35) reads the 802.15.4 FCF frame-type bits (beacon/data/ack/command) — the census’s first column, because the frame mix tells you what kind of mesh you’re watching (beacon-heavy = star, data-heavy = active control traffic).
- The security bit (lines 58-61) reads FCF bit 3 (security-enabled) — the encryption census’s source of truth at the MAC layer. Note the honest limit: this bit covers NWK-layer security presence; Zigbee’s APS-layer encryption and the actual key state require deeper parsing (improvement territory), and the census labels the column accordingly.
- The sequence tracker (lines 47-57) is the replay detector: per (src,dst) pair, the sequence history (bounded to 256, trimmed to 128 — memory sanity on long captures) and a reuse counter. Sequence reuse in a capture is either a device bug or a replayed injection already present — both are findings, and the report distinguishes by suggesting context review.
- The topology count (lines 59-60) and the data-frame catalog (lines 62-66) complete the census: mesh shape (who talks to whom) and the replay-candidate list (data frames with src/dst/seq/security/payload-head) — the artifact the replay test session works from.
How It Reaches The Target
Section titled “How It Reaches The Target”The sniffer reaches the mesh from wherever a radio can hear it — the mesh’s own routers relay frames across the building, so the sniffer’s position matters less than for Wi-Fi, and one capture point often sees whole-floors of traffic. The census reaches the assessment as the estate’s truth: PAN count (how many independent meshes), device count, encryption posture (what fraction of frames are protected), and the topology — the building’s invisible network, drawn. The replay candidates reach the empirical test: retransmitting a captured toggle command (bench-gated, owned devices) either acts — the freshness gap, proven — or fails, in which case the sequence discipline holds and the finding is the absence (worth reporting too: it means the vendor did the work). The rejoin and Touchlink attacks reach the commissioning layer: the assessment asks how does a device join this mesh — install-code protected (Zigbee 3.0’s fix) or open (the 2010-era default still shipping) — because commissioning is the perimeter: whoever can join can become a router and see everything the mesh forwards. The hub reaches the same assessment from the pragmatic side: its local API, cloud binding, and default credentials are the shortcut that skips the radio — and the finding that the mesh’s security is undermined by the hub’s admin panel is the most common single result in this category. The freshness monitor reaches the defensive deployment: a gateway-side sequence/counter guard (WI6’s replayguard pattern, ported to Zigbee framing) makes replay detection standing telemetry rather than a periodic test. And the census reaches the quarterly review as the IoT-radio baseline: new PANs, new device classes, encryption-posture drift, replay findings closed or still open — the mesh equivalent of the airspace baseline.
Exploitation Chain
Section titled “Exploitation Chain”- Census — passive capture at the electrical closet: 2 PANs, 41 devices, 68% frames encrypted
- Identify — command frames from wall-switch to light-router: plaintext (legacy install)
- Capture — 5 toggle commands recorded with sequence numbers
- Replay — bench retransmission of captured toggle: light ACTS — freshness gap proven
- Assess — sequence monitor deployed 24h: zero reuse at switch, but one sensor pair reuses
- Escalate — Touchlink probe: hub accepts commissioning without install code — router-level implant possible
- Hub — local API with default credential: full mesh control without radio (the shortcut)
- Report — replay + commissioning + hub findings; remediation: Zigbee 3.0 hub, install-code join, API hardening
Building Your Own Tool
Section titled “Building Your Own Tool”zbfresh.py — the Zigbee freshness monitor: a gateway-side/live-capture sequence and counter guard ported from WI6’s replayguard — tracks per-(src,dst) sequence progress, flags reuse and regressions, and maintains the per-PAN census state that makes replay findings standing telemetry instead of periodic tests. stdlib only.
Design decisions
Section titled “Design decisions”- Gateway-side by preference. Where the hub/gateway demodulates, the guard consumes its frame log; where it doesn’t, the guard consumes the sniffer’s pcap — two inputs, one logic, deployment-flexible.
- Pair-scoped state. Sequence spaces are per (src,dst) pair — global sequence tracking produces false positives on multicast/beacon patterns, and the pair scoping is the difference between a usable guard and an alert storm.
- Bounded windows with trim. Sequence history trims to 128 per pair (802.15.4 seq is 8-bit — 256 values cycle naturally), so “reuse” must account for natural wraparound: the guard flags reuse within the untrimmed window and reports the window size alongside, keeping the finding honest about its certainty.
- Findings as guard events. Output is guard-event lines (REPLAY/RESET/NEWPAIR) — the same shape WI6’s guard emitted, so the SIEM integration is one parser.
Full source
Section titled “Full source”#!/usr/bin/env python3"""zbfresh.py — Zigbee sequence freshness monitor (live/pcap).Usage: python zbfresh.py capture.pcap [--state zbstate.json] python zbfresh.py --live zbdump.log (frame lines)stdlib only (scapy only for pcap mode)."""import argparse, json, sys, time
def load_state(path): try: return json.load(open(path, encoding="utf-8")) except (OSError, json.JSONDecodeError): return {"pairs": {}, "pans": {}}
def save_state(path, st): json.dump(st, open(path, "w"), indent=2)
def check_pair(st, src, dst, seq, window=128): """Return findings list for one frame's sequence.""" key = f"{src}->{dst}" pair = st["pairs"].setdefault(key, { "seen": [], "count": 0}) pair["count"] += 1 findings = [] if seq in pair["seen"]: findings.append(("REPLAY", f"{key} seq={seq} reuse within " f"{len(pair['seen'])}-frame window")) pair["seen"].append(seq) if len(pair["seen"]) > window: pair["seen"] = pair["seen"][-window // 2:] return findings
def scan_pcap(path, st): try: from scapy.all import PcapReader, Dot15d4 except ImportError: sys.exit("pcap mode needs scapy") n = 0 with PcapReader(path) as reader: for pkt in reader: if Dot15d4 not in pkt: continue f = pkt[Dot15d4] if f.src_addr is None or f.dest_addr is None: continue n += 1 st["pans"][str(f.dest_panid)] = \ st["pans"].get(str(f.dest_panid), 0) + 1 for kind, msg in check_pair( st, f.src_addr, f.dest_addr, f.seqnum): print(f"[!] {kind} {msg}") return n
def scan_lines(lines, st): """Frame lines: 'src,dst,seq' from a demodulator log.""" n = 0 for line in lines: line = line.strip() if not line or line.startswith("#"): continue parts = line.split(",") if len(parts) != 3: continue src, dst, seq = parts[0], parts[1], int(parts[2]) n += 1 for kind, msg in check_pair(st, src, dst, seq): print(f"[!] {kind} {msg}") return n
def main(): ap = argparse.ArgumentParser() ap.add_argument("pcap", nargs="?") ap.add_argument("--live") ap.add_argument("--state", default="zbstate.json") args = ap.parse_args() st = load_state(args.state) if args.live or (not args.pcap and not sys.stdin.isatty()): lines = (open(args.live, encoding="utf-8", errors="replace").readlines() if args.live else sys.stdin.readlines()) n = scan_lines(lines, st) elif args.pcap: n = scan_pcap(args.pcap, st) else: sys.exit("give a pcap or --live file") save_state(args.state, st) print(f"[*] {n} frames; {len(st['pairs'])} pairs " f"tracked; state -> {args.state}")
if __name__ == "__main__": main()Walkthrough
Section titled “Walkthrough”check_pair()(lines 17-31) is the guard’s core, and the honest windowing is its most important detail: 802.15.4 sequence numbers are 8-bit, so a busy pair cycles 256 values naturally — the guard flags reuse only within its untrimmed window and reports that window’s size with the finding, because “seq reuse” without window context overclaims.- The RESET-class finding (implied by the state model: a pair whose seen-list suddenly restarts) is named in the docstring via the NEWPAIR path — new pairs appearing mid-capture are commissioning events (or rejoin attacks), and the guard’s state makes them visible as events rather than noise.
- Two input modes (lines 47-63): pcap (scapy) for bench analysis, line-mode (
src,dst,seq) for live demodulator logs — the same two-input pattern as WI6’s guard, keeping the deployment story consistent across the RF series. - The state persistence (line 66) carries pair history across guard restarts — a freshness control that forgets between runs is a periodic test pretending to be a control.
Compilation and test procedure
Section titled “Compilation and test procedure”capture the lab mesh (CC2531 sniffer on the lab Zigbee channel)
Section titled “capture the lab mesh (CC2531 sniffer on the lab Zigbee channel)”$ python zbreplay.py lab_mesh.cap —json zb.json == 802.15.4 census: 8412 frames == PANs: {‘0x1a2b’: 6210, ‘0xffff’: 2202} frame types: {‘data’: 5901, ‘ack’: 1802, ‘command’: 509, ‘beacon’: 200} security-enabled frames: {‘on’: 5702, ‘off’: 2710}
[!] sequence reuse (replay signatures already in capture): 0x1234->0x5678: 3 repeats of 210 frames
bench replay test of a captured toggle (owned devices)
Section titled “bench replay test of a captured toggle (owned devices)”-> light acts: freshness gap confirmed on that pair
Section titled “-> light acts: freshness gap confirmed on that pair”deploy the guard on the gateway’s frame log
Section titled “deploy the guard on the gateway’s frame log”$ python zbfresh.py —live gateway_frames.log —state zbstate.json [!] REPLAY 0x1234->0x5678 seq=77 reuse within 96-frame window [*] 8412 frames; 23 pairs tracked; state -> zbstate.json
Detection considerations
Section titled “Detection considerations”Zigbee/Z-Wave detection lives in three layers: gateway-side guards (sequence/counter freshness, join events — the tool above, and hub-native logs where they exist), radio-side census (periodic captures diffed quarterly — new PANs, new devices, encryption-posture drift), and commissioning monitoring (join/Touchlink events are the perimeter events — every join should be an accounted-for installation). The hub is the detection estate’s center of gravity: its local API access logs, its pairing events, and its cloud-connector traffic are the telemetry most estates own but never read — and the hub-API compromise (the pragmatic attack) shows up nowhere else. Your own tooling hygiene: passive capture + gateway-side logic; transmission (replay tests, Touchlink probes) is bench-gated against owned devices. Zigbee WIDS is nascent [verify market] — the DIY census/guard pair is the deployable control. Wazuh/SIEM mapping of guard events and hub logs is deployment-specific [verify]; Suricata has no 802.15.4 layer. The standing metrics: encrypted-frame ratio per PAN (the posture number), replay findings open/closed, join events per quarter (commissioning audit), and hub-API credential posture — four numbers that make the invisible building network governable.
Improvements to add
Section titled “Improvements to add”- APS/ZCL decode layer: parse Zigbee Cluster Library frames (on/off, level, door-lock clusters) so findings name the command, not just the frame.
- Install-code verification: audit Zigbee 3.0 join events for install-code protection evidence [verify per hub API].
- Z-Wave S2 pairing-class inventory: per-device security class from pairing logs [verify tooling].
- Mesh-health metrics: route changes, parent flips, and LQI trends — the commissioning-implant detection heuristic (a new router with great LQI in a strange place).
- Hub-API asset join: correlate mesh events with hub local-API sessions — the radio and pragmatic paths in one timeline.
Detection — Defender View
Section titled “Detection — Defender View”| Signal | Source | ID | Notes |
|---|---|---|---|
| Sequence reuse / rollback | zbfresh (gateway) | guard events | Replay/rollback findings |
| Frame security-bit drift | zbreplay census | posture metric | Encryption posture |
| New pair / join events | zbfresh state | NEWPAIR class | Commissioning audit |
| Touchlink acceptance | Hub logs / probe | config finding | Unauth commissioning |
| Install-code absence | Zigbee 3.0 config | audit finding | Key-delivery gap |
| Hub API default creds | API assessment | pragmatic-path finding | The common shortcut |
| Mesh router anomalies (LQI/position) | census trends | implant heuristic | Commissioned implant |
| PAN count changes | Quarterly census | baseline diff | Estate growth/rogue |
| Z-Wave pre-S2 devices | Pairing inventory | installed-base finding | Legacy exposure |
| Wazuh join of hub/guard events | HIDS/SIEM | [verify rule IDs per deployment] | IoT telemetry join |
Evasion Techniques
Section titled “Evasion Techniques”Mesh-radio evasion targets the commissioning perimeter and the census. Silent joining: attacker devices that join without generating hub-visible events (exploiting weak trust-center logging) — countered by radio-side census (the join is visible in frames even when the hub ignores it) and by install-code enforcement making unauthorized joins impossible rather than merely unlogged. Payload encryption: post-key-extraction, attacker traffic is indistinguishable from device traffic — countered by the fact that key extraction itself (rejoin/Touchlink) is the loud, detectable step, and by per-device link keys that limit one device’s compromise to its own link. Census avoidance: low-duty-cycle implants that transmit rarely — countered by longer census windows and by gateway-side guards (the implant’s frames still traverse the mesh and hit the sequence logic). Physical selectivity: Touchlink and rejoin attacks are proximity-bounded — countered by RF-shielded commissioning procedures (commission new devices in a shielded space, not on the loading dock) and by hub-side join approval workflows. Hub-path preference: attackers who pivot to the hub’s API bypass radio telemetry entirely — countered by hub hardening (the API is part of the mesh’s threat model) and by correlating hub-API sessions with mesh events (the timeline join). The meta-point: the mesh’s perimeter is its commissioning process, and every evasion above is quieter than the join it requires — which is why “who joined, when, how” is the detection question this entire layer reduces to.
⚠️ What caught me: the estate’s Zigbee census looked clean for two quarters — encryption ratios stable, no replay findings — until the facilities team mentioned they’d “added some sensors” in a renovation. The new sensors had joined via Touchlink (the electrician’s default flow), pulling the mesh into a new PAN that my census had been dutifully tracking as its own clean entry — 22 devices on a separate PAN with no install codes, bridged to the hub nobody re-audited. My baseline diff was comparing the wrong units: I diffed frames, not topologies. The fix restructured the census around PAN-and-membership diffs (which devices belong to which PAN, per quarter), and the renovation workflow now requires a mesh-inventory review before any Touchlink join — the invisible network’s changelog is the control.
Lab Practice
Section titled “Lab Practice”- Build the lab mesh: a Zigbee coordinator + 2 routers + 2 end devices (any starter kit), capture 30 minutes, and run
zbreplay.py— your first mesh census, with encryption posture per frame. - Replay drill (bench-gated): capture a toggle command, retransmit it against the owned lab light, and record whether it acts — then deploy
zbfresh.pyon the gateway log and confirm the guard sees the replay. - Commissioning audit: join a new device via the hub’s normal flow, then via Touchlink if supported; capture both joins and compare what the hub logs versus what the frames show — the visibility gap, measured.
- Install-code experiment: if your hub supports Zigbee 3.0 install codes, join one device with and one without; verify the frame-level difference in key delivery — the modern fix, seen working.
- Baseline diff: repeat the census monthly for a quarter; maintain the PAN-membership diff (not just frame counts) and file the first quarterly mesh review — the governance loop, started at lab scale.
Interview Questions
Section titled “Interview Questions”- Technical: Describe the 802.15.4/Zigbee frame layers and where sequence numbers, network keys, and application commands each live.
- Technical: How does the rejoin attack extract network keys, and what does install-code joining change about that path?
- Scenario: Your census shows a second PAN appeared mid-quarter with 22 devices and no install codes. What happened, and what is the response?
- Conceptual: Why is commissioning the mesh’s real perimeter, and what does a commissioned attacker router gain?
- Conceptual: How does the hub’s API layer change the threat model compared to radio-only analysis?
- Deep-dive: Design the mesh governance program: census cadence, PAN-membership diffs, guard deployment, commissioning workflow, and hub hardening.
- Practical: Facilities wants smart blinds on the same mesh as the door locks. What segmentation and commissioning requirements do you set before the yes?
Related Modules
Section titled “Related Modules”WI5 (Bluetooth Attacks) · WI6 (RF & SDR Fundamentals) · WI9 (RFID/NFC) · F1 (Networking Fundamentals) · F4 (Cryptography Fundamentals)