MQTTを利用したサービスの攻撃シナリオを検証してみた
下記のAvastのブログで2018年8月時点のMQTTに関する情勢や、攻撃シナリオについて解説していました。
とても興味深かったので、攻撃シナリオの中の1つをローカル環境で検証してみました。
Are smart homes vulnerable to hacking?
https://blog.avast.com/mqtt-vulnerabilities-hacking-smart-homes
目次
この記事の目的
攻撃シナリオを通して、MQTTを適切に利用しなかった場合の危険性を感じてもらい、安全なシステム開発につなげてもらえればと考えています。
MQTTとは?
参照: Hacking the IoT with MQTT – Morphus Labs
図のようにBrokerを介してPubliisherからSubscriberへメッセージを送信します。
MQTT自体はシンプルなプロトコルを旨としているらしく、「認証」や「暗号化」、「接続元の確認」といった機能はもっていません。
MQTTの利用状況
Avastの記事によると、2018年8月頃の時点で、49,197台のMQTTサーバがインターネットに公開されており、そのうち32,888台にはパスワード無しでアクセスすることができる状態だったそうです。
参照: At least 32,000 smart homes and businesses at risk of leaking data | Avast
検証
それでは検証をはじめます。
検証環境
Ubuntu 16.04
MQTT Brokerをインストール
こちらの記事を参照して、MosquittoというMQTTブローカーをインストールしました。
UbuntuにMosquittoをインストールしてMQTTブローカーを構築 - Qiita
$ sudo add-apt-repository ppa:mosquitto-dev/mosquitto-ppa $ sudo apt-get update $ sudo apt-get install mosquitto
MQTT動作確認
publisherとsubscriberを作成します。
「paho-mqttwo」を使ってサンプルコードを作成しました。
paho-mqttwoインストール
$ pip install paho-mqtt
今回はローカルにBroker設置しているので、接続先IPアドレスは「127.0.0.1」です。
ポートはMQTTのデフォルトの「1883」を指定します。
Topicは「mqtt-test」というTopicで、「test」というメッセージを送信しました。
本来はサンプルコードの全てを載せた方がいいのでしょうが、検証内容の性質上、ソースコードは割愛しています。
悪意の無い簡単なサンプルコードでも、色々とややこしいことになる場合があるらしいので。
publisher.py(一部抜粋)
host = '127.0.0.1' port = 1883 topic = 'mqtt-test'
subscriber.py(一部抜粋)
host = '127.0.0.1' port = 1883 topic = 'mqtt-test'
publisherとsubscriberを作成したら、subscriberを起動します。
$ python subscriber.py
publisherでMQTTメッセージを送信します。
$ python publisher.py
publisher.pyから送信した「test」という文字をshubscriber.pyで受け取ることができました。
正常系の動作確認が終わったので、攻撃シナリオの検証に移ります。
攻撃シナリオ概要
今回は、「自宅ガレージの扉にIoT鍵が設置されていて、スマホアプリから解錠命令を送信することで扉を開けることができる」というシナリオで話を進めます。
※このシナリオは攻撃シナリオをイメージしてもらうためのフィクションです。実在する製品とは一切関係ありません。
攻撃者は、下記のような流れで攻撃を実施します。
攻撃対象となるMQTTサーバを見つける
shodanを使ったり、各種スマホアプリやIoTデバイスの通信処理を解析することで、攻撃対象となるMQTTサーバのIPアドレスを特定します。
情報収集
対象となるMQTTサーバに接続したら、まずは情報収集です。
今回正規のクライアントは「/random-123abc/house/garage/」というTopicでメッセージをやり取りします。
「random-123abc」の部分は、利用者を一意に定めるランダムなIDなどが入るイメージです。
攻撃者は「#」というワイルドカードを使って全てのTopicの内容を受信します。
subscriber-attacker.py(一部抜粋)
host = '127.0.0.1' port = 1883 topic = '#'
subscriber-user.py(一部抜粋)
host = '127.0.0.1' port = 1883 topic = '/random-123abc/house/garage/'
publisher.py(一部抜粋)
host = '127.0.0.1' port = 1883 topic = '/random-123abc/house/garage/'
攻撃者を想定したsubscriber-attacker.pyと、正規の利用者を想定したsubscriber-user.pyを起動した後、publisher.pyでメッセージを送信します。
ワイルドカードを利用した攻撃者が、正規のメッセージを受信できました。
解析
攻撃者は「/random-123abc/house/garage」のTopicに対して、json形式のメッセージを送信してやればいいことがわかります。
攻撃
あとは、判明したTopicに対して攻撃者がメッセージを送信することで任意にガレージの扉を操作することができます。
感想
非常にシンプルなサンプルコードでAvastの記事に記載されていた攻撃シナリオを検証することができました。
似たような記事で「ワイルドカードでメッセージを受信したところ、利用者の位置情報を取得するとができた」というような情報もありました。おそらく、スマートウォッチなどのウェアラブルデバイスや、位置をロギングするようなサービスだったのでしょう。
MQTT自体は非常にシンプルなプロトコルで、認証認可や暗号化の機能は持っていません。
そのため、アプリケーション開発者の方が、サービスに合わせた認証認可処理や暗号化処理を準備する必要があります。
この記事が、「便利で安全なサービス」が世の中に生まれる一助になれば幸いです。