1883 - Pentesting MQTT (Mosquitto)

Support HackTricks

Basic Information

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

기본 포트: 1883

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

트래픽 검사

MQTT 브로커가 CONNECT 패킷을 수신하면 CONNACK 패킷이 다시 전송됩니다. 이 패킷에는 연결 상태를 이해하는 데 중요한 반환 코드가 포함되어 있습니다. 반환 코드 0x00은 자격 증명이 수락되었음을 의미하며, 성공적인 연결을 나타냅니다. 반면, 반환 코드 0x05는 자격 증명이 유효하지 않음을 나타내어 연결을 방지합니다.

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

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

MQTT 펜테스팅

인증은 완전히 선택 사항입니다 그리고 인증이 수행되고 있더라도, 기본적으로 암호화가 사용되지 않습니다 (자격 증명이 평문으로 전송됩니다). MITM 공격을 통해 여전히 비밀번호를 훔칠 수 있습니다.

MQTT 서비스에 연결하려면: https://github.com/bapowell/python-mqtt-client-shell을 사용하고 다음을 수행하여 모든 주제에 구독할 수 있습니다:

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

당신은 또한 사용할 수 있습니다:

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 서비스에 연결하고 모든 주제를 구독하여 수신할 수 있습니다:

#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/#')

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

More information

from here: https://morphuslabs.com/hacking-the-iot-with-mqtt-8edaf0d07b9b

The Publish/Subscribe Pattern

The publish/subscribe model is composed of:

  • Publisher: 브로커의 하나(또는 여러 개) 주제에 메시지를 게시합니다.

  • Subscriber: 브로커의 하나(또는 여러 개) 주제를 구독하고, 퍼블리셔로부터 전송된 모든 메시지를 수신합니다.

  • Broker: 퍼블리셔로부터 구독자에게 모든 메시지를 라우팅합니다.

  • Topic: 슬래시로 구분된 하나 이상의 레벨로 구성됩니다 (예: /smartshouse/livingroom/temperature).

Packet Format

Every MQTT packet contains a fixed header (Figure 02).Figure 02: Fixed Header

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

Packet Types

  • 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는 예약으로 표시되며 사용이 금지됩니다.

Shodan

  • port:1883 MQTT

Support HackTricks

Last updated