Apache DolphinScheduler任意文件写到RCE
字数 1151 2025-08-22 22:47:30
Apache DolphinScheduler 任意文件写入到RCE漏洞分析
0x01 产品介绍
Apache DolphinScheduler 是一个开源的分布式工作流任务调度系统,旨在通过图形化界面帮助用户更高效地管理任务调度和数据流控制。它特别适用于大数据领域的任务调度和工作流编排。
0x02 漏洞危害
- 漏洞类型:任意文件写入导致远程代码执行(RCE)
- 影响版本:Apache DolphinScheduler <= 3.2.1
- 危害:
- 敏感信息泄露
- 写入恶意后门
- 系统完全控制
0x03 环境搭建
使用Docker快速搭建测试环境:
docker run --name dolphinscheduler-standalone-server -p 12345:12345 -p 25333:25333 -d apache/dolphinscheduler-standalone-server:3.2.0
0x04 漏洞分析
漏洞位置
漏洞存在于org.apache.dolphinscheduler.api.service.impl#updateResource函数中,由于资源管理功能未对currentDir参数进行有效校验。
关键代码分析
public Result<Object> updateResource(User loginUser, String resourceFullName,
String resTenantCode, String name,
ResourceType type, MultipartFile file) {
// ...省略部分代码...
// 获取文件状态
String defaultPath = storageOperate.getResDir(tenantCode);
StorageEntity resource;
try {
resource = storageOperate.getFileStatus(resourceFullName, defaultPath, resTenantCode, type);
} catch (Exception e) {
log.error("Get file status fail, resource path: {}", resourceFullName, e);
putMsg(result, Status.RESOURCE_NOT_EXIST);
throw new ServiceException((String.format("Get file status fail, resource path: %s", resourceFullName)));
}
// ...省略部分代码...
// 文件上传逻辑
if (file != null) {
if (!upload(loginUser, fullName, file, type)) {
log.error("Storage operation error, resourceName:{}, originFileName:{}.",
name, RegexUtils.escapeNRT(file.getOriginalFilename()));
putMsg(result, Status.HDFS_OPERATION_ERROR);
throw new ServiceException(String.format("upload resource: %s file: %s failed.",
name, file.getOriginalFilename()));
}
if (!fullName.equals(originFullName)) {
try {
storageOperate.delete(originFullName, false);
} catch (IOException e) {
log.error("Resource delete error, resourceFullName:{}.", originFullName, e);
throw new ServiceException(String.format("delete resource: %s failed.", originFullName));
}
}
ApiServerMetrics.recordApiResourceUploadSize(file.getSize());
return result;
}
// 文件重命名逻辑
String destHdfsFileName = fullName;
try {
log.info("start copy , originFullName , destHdfsFileName);
storageOperate.copy(originFullName, destHdfsFileName, true, true);
putMsg(result, Status.SUCCESS);
} catch (Exception e) {
log.error(MessageFormat.format(" copy {0} -> {1} fail", originFullName, destHdfsFileName), e);
putMsg(result, Status.HDFS_COPY_FAIL);
throw new ServiceException(MessageFormat.format(Status.HDFS_COPY_FAIL.getMsg(),
originFullName, destHdfsFileName));
}
return result;
}
漏洞利用思路
- 任意文件修改:可以修改web根目录下已存在的文件
- 文件重命名:可以将任意文件重命名为.jsp等可执行文件
- 系统文件修改:直接修改/etc/shadow等系统关键文件
实际利用过程
- 尝试修改web目录下的文件,但未发现.jsp文件
- 发现可以修改任意存在文件的名称
- 尝试修改favicon.ico为.jsp文件,但发现不解析jsp文件
- 考虑覆盖xml热部署加载实现jsp解析
- 最终采用修改/etc/shadow文件添加后门账户的方法
成功利用
通过修改/etc/shadow文件添加后门账户:
- 如果用户有SSH权限,可直接SSH登录
- 若无SSH权限,可尝试修改/etc/ssh/sshd_config文件
0x05 漏洞总结
可能的利用方式
-
Linux系统:
- 修改/etc/shadow添加后门账户
- 修改/etc/ssh/sshd_config开启root登录
- 覆盖crontab文件实现定时任务
- 修改.bashrc等配置文件实现持久化
-
Windows系统:
- 修改用户账户数据库
- 覆盖启动项
- 修改系统配置文件
-
Web应用:
- 覆盖XML配置文件实现热部署
- 修改静态文件插入恶意代码
- 覆盖日志文件实现日志污染
相关漏洞
- 该框架还存在任意文件读取漏洞,路径为
/dolphinscheduler/resources/download - 最新版本已对该漏洞进行过滤
0x06 修复建议
- 升级到最新版本
- 对文件路径参数进行严格校验
- 限制文件操作权限
- 实施最小权限原则