# MQTT Topic Discovery and Structure Mapping

- **URL:** https://hackindex.io/services/mqtt/enumeration/mqtt-topic-discovery
- **Path:** MQTT > Enumeration
- **Up:** [Enumeration](https://hackindex.io/services/mqtt/enumeration.md)
- **Published:** 2026-03-16
- **Updated:** 2026-03-16

MQTT topics are hierarchical strings that publishers and subscribers use to route messages: for example `factory/line1/sensor/temperature` or `home/bedroom/light/state`. The topic structure reveals:

- What devices are connected and their hierarchy
- What data each device produces (telemetry, state, logs)
- What control channels exist (cmd, set, command topics)
- Whether credentials or configuration payloads are in transit

Subscribing to wildcard patterns captures everything the broker is willing to show you.

This page assumes you can connect to the broker. If authentication is required, confirm credentials first.

## MQTT Topic Enumeration with Wildcard Subscribe

The `#` wildcard matches all topics at all levels. This is the first subscription to try:

```bash
mosquitto_sub -h $TARGET_IP -p 1883 -t '#' -v
```

`-v` prints the topic name alongside the payload. Let this run for at least 30 seconds: IoT devices often publish on slow intervals (sensor readings every 30s or 60s are common).

```
home/thermostat/temperature 22.5
home/doorbell/state pressed
factory/pump/rpm 1450
factory/pump/control {"cmd":"stop"}
credentials/backup admin:mqtt2024
```

Every line is a live message. The topic path tells you the device hierarchy. Payloads reveal data format: JSON, plain text, binary.

## Subscribe to Retained Messages Only

Retained messages are stored on the broker and delivered immediately to any new subscriber. They often contain the last known state of every device: useful for a fast snapshot without waiting for live traffic:

```bash
mosquitto_sub -h $TARGET_IP -p 1883 -t '#' -v --retained-only -C 100
```

`--retained-only` exits after receiving retained messages. `-C 100` stops after 100 messages. Adjust the count based on how many topics you expect.

## Wildcard Enumeration by Level

If `#` is ACL-restricted, try single-level wildcards to map the top-level namespace first:

```bash
mosquitto_sub -h $TARGET_IP -p 1883 -t '+' -v -C 20
mosquitto_sub -h $TARGET_IP -p 1883 -t '+/+' -v -C 50
mosquitto_sub -h $TARGET_IP -p 1883 -t '+/+/+' -v -C 50
```

`+` matches exactly one level. Incrementing the depth reveals nested topic structures that a flat `#` subscription might not expose when partial ACLs are in place.

## Targeted Topic Subscriptions

Once you have a partial picture of the namespace from wildcard results, target specific paths of interest:

```bash
mosquitto_sub -h $TARGET_IP -p 1883 -t 'credentials/#' -v
mosquitto_sub -h $TARGET_IP -p 1883 -t 'config/#' -v
mosquitto_sub -h $TARGET_IP -p 1883 -t 'admin/#' -v
mosquitto_sub -h $TARGET_IP -p 1883 -t 'device/#' -v
mosquitto_sub -h $TARGET_IP -p 1883 -t 'cmd/#' -v
mosquitto_sub -h $TARGET_IP -p 1883 -t 'control/#' -v
```

Topics named `cmd`, `control`, `set`, or `command` are write paths: these are the targets for [Unauthorized MQTT Publish](https://hackindex.io/services/mqtt/exploitation/mqtt-unauthorized-publish).

## Log All Traffic to File

For longer passive observation, log everything with timestamps:

```bash
mosquitto_sub -h $TARGET_IP -p 1883 -t '#' -v --line-buffered | while read line; do echo "$(date -u +%H:%M:%S) $line"; done | tee /tmp/mqtt-traffic.txt
```

Review the log for patterns: repeated credential strings, device identifiers, control commands, JSON config payloads.

## Map the Topic Tree

After collecting traffic, extract the unique topic paths to understand the full structure:

```bash
awk '{print $1}' /tmp/mqtt-traffic.txt | sort -u
```

Group by top-level prefix to identify device categories, then map which topics receive writes versus reads to identify control channels.

## References

- [mosquitto_sub man page](https://mosquitto.org/man/mosquitto_sub-1.html) - Wildcard syntax, --retained-only, -C count, and -v verbose flag reference
- [MQTT 3.1.1 Specification: Topic Names and Filters](https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718106) - Formal definition of + and # wildcard behaviour
