1. 漏洞概述

Apache DolphinScheduler 的 Master 进程负责接收任务调度请求、维护工作流运行状态,并通过内置的 Netty RPC 框架与 Worker / API-Server 等组件通讯。该 RPC 服务在默认配置下监听 5678/TCP,对集群外部网络可见。Master 节点携带一组任务插件,其中 LogicFakeTask 属于测试型插件,却在生产包中默认启用。插件的实现允许执行任意 Shell 脚本。

  • 类别:未授权远程命令执行(RCE)。
  • 目标端点:Master RPC 服务(MasterRpcServer)。
  • 漏洞根源:RPC 接口缺乏认证、请求参数未校验、LogicFakeTask 任意脚本执行。
  • 利用结果:可在 Master 主机以 Master 进程权限(通常为 root)执行任意命令,进而控制整套调度系统。

2. 影响范围

  • 版本:在 3.3.2 版本上验证成功,所有默认携带 LogicFakeTask 且未对 RPC 加固的版本均受影响。
  • 部署拓扑:无论单 Master 还是多 Master(单机部署和集群部署),只要 RPC 端口可访问即可复现。
  • 网络范围:当 5678/TCP 暴露在内网甚至互联网时,攻击面进一步扩大。

3. 攻击流程还原

  1. 掌握端口信息:扫描 Master 地址发现 5678/TCP 开放。

  2. 构造 RPC 调用

    • methodIdentifier 指向 ILogicTaskExecutorOperator.dispatchTask

      1
      public abstract TaskExecutorDispatchResponse dispatchTask(TaskExecutorDispatchRequest request)
    • argsTypes 设置为 org.apache.dolphinscheduler.task.executor.operations.TaskExecutorDispatchRequest

    • args 填充伪造的 TaskExecutionContext,指定 taskType=LogicFakeTasktaskParams={"shellScript":"<恶意命令>"}

  3. 发送 TCP 数据包:遵循 Netty Transporter 协议封装后直接写入 socket。

  4. Master 无鉴权执行:Master 解析请求后创建 LogicFakeTask,并在 ProcessBuilder("/bin/sh", "-c", shellScript) 中执行指定的命令。

  5. 风险:可植入后门、窃取凭据、横向移动至 Worker/数据库/存储系统。

4. 漏洞代码细节

4.1 RPC 方法暴露

SpringServerMethodInvokerDiscovery 会扫描所有 @RpcService 接口,将其方法注册到 ServerMethodInvoker 列表中:

1
2
3
4
5
6
7
8
9
for (Method method : anInterface.getDeclaredMethods()) {
RpcMethod rpcMethod = method.getAnnotation(RpcMethod.class);
if (rpcMethod == null) {
continue;
}
ServerMethodInvoker serverMethodInvoker =
new ServerMethodInvokerImpl(serverMethodInvokerProviderBean, method);
nettyRemotingServer.registerMethodInvoker(serverMethodInvoker);
}

ServerMethodInvokerImpl 中,调用完全缺乏鉴权逻辑:

1
2
3
4
5
6
7
8
@Override
public Object invoke(Object... args) throws Throwable {
try {
return method.invoke(serviceBean, args);
} catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}

任意客户端只要知道 methodIdentifier,即可直接调用目标方法。

4.2 LogicFakeTask 任意命令执行

LogicFakeTaskstart() 方法中核心片段:

1
2
3
4
5
6
7
8
9
10
String shellScript = ParameterUtils.convertParameterPlaceholders(
taskParameters.getShellScript(),
ParameterUtils.convert(taskExecutionContext.getPrepareParamsMap()));

if (StringUtils.isNotEmpty(taskExecutionContext.getEnvironmentConfig())) {
shellScript = taskExecutionContext.getEnvironmentConfig() + "\n" + shellScript;
}
ProcessBuilder processBuilder = new ProcessBuilder("/bin/sh", "-c", shellScript);
processBuilder.redirectErrorStream(true);
process = processBuilder.start();

taskParameters.getShellScript() 来自 RPC 请求体,可随意构造。Master 节点会直接执行该脚本。

4.3 请求参数可伪造性

TaskExecutionContext 通过构造并经 JSON 反序列化,还原后进入业务逻辑,没有任何合法性校验:

1
taskExecutionContext = jsonMapper.readValue(taskParamsJson, TaskExecutionContext.class);

5. 复现

  1. 在可访问 Master RPC 端口的主机上执行:

    1
    2
    3
    go run master_rpc_logic_fake_rce_poc.go \
    -target 10.1.1.10:5678 \
    -cmd 'touch /tmp/master_rpc_rce_go'
  2. 预期响应:输出 [+] 成功触发 LogicFakeTask 执行...,表示 Master 接受任务。

  3. 登录 Master 主机检查:

    1
    ls /tmp | grep master_rpc_rce_go
  4. 查看 Master 日志确认:

    1
    2
    Receive TaskExecutorDispatchRequest(... taskName=logic_fake_rpc_poc, taskType=LogicFakeTask ...)
    LogicFakeTask: logic_fake_rpc_poc execute success

成功写入文件

6. 风险

  • Master 服务通常以高权限账户运行,可执行任意系统命令。
  • 触发门槛低,无需任何内部凭证。
  • 可扩展为对整个调度/数据平台的全面控制。

7. 修复建议

网络隔离:限制对 5678/TCP 的访问,仅允许内部受信主机访问。

8 .利用脚本

https://github.com/52hertzi/DolphinScheduler-Master-RPC-LogicFakeTask-RCE/blob/master/master_rpc_logic_fake_rce_poc.go

9.注意事项

  • 本脚本仅用于安全测试目的,请勿在未授权环境中使用。