Wiki / Protocols

MQTT

Lightweight IoT pub/sub messaging: often anonymous, leaking telemetry and accepting commands.

Pub/sub through the broker
Broker :1883
home/door/lock
sub: app
pub: lock
home/temp
sub: dashboard
Clients never talk to each other directly. Publishers send messages to a topic on the broker; the broker fans each message out to every client subscribed to that topic. A client can be both: a smart lock subscribes to its command topic and publishes its state. Wildcards + (one level) and # (all levels) let one subscriber read whole subtrees.

MQTT (Message Queuing Telemetry Transport) is a lightweight publish/subscribe messaging protocol where clients never speak to each other directly but exchange messages through a central broker, organised into a hierarchy of topics. Its tiny footprint made it the default nervous system of IoT fleets and home-automation hubs.

What it is

An MQTT client opens a long-lived TCP connection to a broker (plaintext on port 1883, TLS on 8883) and then either publishes messages to a topic or subscribes to one. A topic is a UTF-8 path like home/door/lock; the broker matches published topics against subscriptions and delivers accordingly. Two wildcards make subscriptions powerful: + matches exactly one level (home/+/lock) and # matches everything below a point (home/#, or # for the entire tree). MQTT adds quality-of-service levels (0 fire-and-forget, 1 at-least-once, 2 exactly-once), retained messages (the broker keeps the last value on a topic for new subscribers), and a Last Will and Testament the broker publishes when a client drops.

Why it matters

Entire device fleets pipe their telemetry and receive their commands over one broker, and brokers are routinely misconfigured to allow anonymous connections. When they do, # hands you every message flowing through the system: sensor readings, GPS traces, firmware URLs, and often credentials or tokens in cleartext. Worse, the same open broker will accept your publishes, so if a device subscribes to home/door/lock and blindly obeys, you send it OPEN. Shodan indexes tens of thousands of exposed 1883 brokers precisely because so many ship with allow_anonymous true.

How to attack it

Find the broker, drink from the firehose, then test whether you can command:

# 1. Find brokers on a network (or via Shodan: port:1883 "MQTT").
nmap -p 1883,8883 --open 10.0.0.0/24

# 2. Subscribe to everything and watch the whole system in the clear.
mosquitto_sub -h 10.0.0.5 -t '#' -v          # -v prints topic + payload

# 3. Read leaked telemetry, credentials, and the topic structure.

# 4. Publish a command onto a control topic a device trusts.
mosquitto_pub -h 10.0.0.5 -t 'home/door/lock' -m 'OPEN'

# 5. Test authentication and ACLs (do creds gate publish? subscribe? both?).
mosquitto_sub -h 10.0.0.5 -u admin -P admin -t '#' -v

Read the retained messages first (they often expose the last known state and config without waiting for live traffic), and check $SYS/# on brokers that expose it for broker stats and connected-client counts.

Pitfalls

  • QoS 2 and retained confuse newcomers: a retained message means a topic can look "live" when nothing is currently publishing. That is stored state, not a current event.
  • Authentication and authorization are separate. A broker may require a username yet still apply a wildcard-open ACL, so authenticated does not mean scoped.
  • Topic names are case-sensitive and have no inherent schema; the meaning of a payload (OPEN, 1, a JSON blob) is entirely up to the device. Watch real traffic before forging.
  • # on a busy broker is a lot of data. Filter to a subtree once you know the layout, and never assume the broker you touched is one you are allowed to touch.

Further reading