首页 网络安全 正文
  • 本文约970字,阅读需5分钟
  • 3
  • 0

MONAI 路径遍历漏洞CVE-2026-21851

摘要

栋科技漏洞库关注到 MONAI 的_download_from_ngc_private()函数路径遍历(Zip Slip)漏洞,追踪CVE-2026-21851,CVSS 3.X分 5.3。

MONAI(Medical Open Network for AI)是由 NVIDIA 与顶级学术医疗中心联合发起的医疗影像深度学习开源框架,其基于 PyTorch 构建。

一、基本情况

MONAI核心价值是标准化医疗 AI 全生命周期开发、解决医学影像数据(3D/4D、DICOM、标注稀缺)挑战,打通科研到临床的落地路径。

MONAI 路径遍历漏洞CVE-2026-21851

提供从数据标注、模型训练到临床部署完整工具链,兼顾研究灵活性与临床合规性,支持 NVIDIA GPU 加速与AMD ROCm异构计算环境。

栋科技漏洞库关注到 MONAI 的_download_from_ngc_private()函数路径遍历(Zip Slip)漏洞,追踪CVE-2026-21851,CVSS 3.X分 5.3。

二、漏洞分析

CVE-2026-21851漏洞是包含1.5.1版本在内的早期版本中MONAI的_download_from_ngc_private()函数中存在路径遍历(Zip滑动)漏洞。

该函数在未进行路径验证的情况下使用了zipfile.ZipFile.extractall()。

在同一代码库中,其他类似的下载函数则正确地使用了现有的safe_extract_member()函数。

这似乎是一个实现上的疏忽,因为安全提取功能已在MONAI的其他地方实现并使用。

1、易受攻击的代码位置

文件:monai/bundle/scripts.py

第291-292行

函数:_download_from_ngc_private()

# monai/bundle/scripts.py - Lines 284-293
zip_path = download_path / f"{filename}_v{version}.zip"
with open(zip_path, "wb") as f:
    f.write(response.content)
logger.info(f"Downloading: {zip_path}.")
if remove_prefix:
    filename = _remove_ngc_prefix(filename, prefix=remove_prefix)
extract_path = download_path / f"{filename}"
with zipfile.ZipFile(zip_path, "r") as z:
    z.extractall(extract_path)  # <-- No path validation
    logger.info(f"Writing into directory: {extract_path}.")

2、根本原因

代码直接调用z.extractall(extract_path),而未验证存档成员路径是否位于解压目录内。

3、安全代码已存在

MONAI已在monai/apps/utils.py(第125-154行)中提供了一个安全提取函数,该函数能够正确验证路径:

def safe_extract_member(member, extract_to):
    """Securely verify compressed package member paths to prevent path traversal attacks"""
    # ... path validation logic ...

    if os.path.isabs(member_path) or ".." in member_path.split(os.sep):
        raise ValueError(f"Unsafe path detected in archive: {member_path}")

    # Ensure path stays within extraction root
    if os.path.commonpath([extract_root, target_real]) != extract_root:
        raise ValueError(f"Unsafe path: path traversal {member_path}")

三、POC概念验证

1、创建一个恶意Zip文件

管理员已设置登录后刷新可查看

输出:

Created: malicious_bundle.zip
Contents:
  - monai_test_bundle/configs/metadata.json
  - ../../../tmp/escaped_file.txt

2、展示差异

此脚本展示了易受攻击的模式(在_download_from_ngc_private中使用)与安全模式(在MONAI的其他地方使用)之间的差异:

管理员已设置登录后刷新可查看

输出:

==================================================
VULNERABLE PATTERN (scripts.py:291-292)
==================================================
[VULNERABLE] Extraction completed without validation
  Extracted: monai_test_bundle/configs/metadata.json
  Extracted: tmp/escaped_file.txt

==================================================
SAFE PATTERN (apps/utils.py)
==================================================
[SAFE] Allowed: monai_test_bundle/configs/metadata.json
[SAFE] BLOCKED: ../../../tmp/escaped_file.txt

3、影响

利用利用所需条件

·攻击者必须控制或破坏一个NGC私有仓库

·受害者必须配置MONAI以从该存储库下载

·受害者必须使用source="ngc_private"参数

4、潜在影响

如果被利用,攻击者可能会在预期的解压目录之外写入文件。实际影响取决于:

运行MONAI的用户的权限

已泄露文件的目标位置

Python版本(较新版本内置了一些路径规范化功能)

5、缓解因素

要求攻击者控制一个NGC私有仓库

现代Python版本(3.12及以上)内置了一些路径规范化功能

与其他源相比,ngc_private源的使用频率较低

6、推荐修复方案

将直接的extractall()调用替换为MONAI现有的安全提取方法:

# monai/bundle/scripts.py

+ from monai.apps.utils import _extract_zip

def _download_from_ngc_private(...):
    # ... existing code ...

    extract_path = download_path / f"{filename}"
-   with zipfile.ZipFile(zip_path, "r") as z:
-       z.extractall(extract_path)
-       logger.info(f"Writing into directory: {extract_path}.")
+   _extract_zip(zip_path, extract_path)
+   logger.info(f"Writing into directory: {extract_path}.")

这使_download_from_ngc_private()函数与其他下载函数保持一致,并确保所有下载源的安全性一致。

四、影响范围

MONAI <= 1.5.1

五、修复建议

MONAI > 1.5.1

六、参考链接

管理员已设置登录后刷新可查看



扫描二维码,在手机上阅读
评论
更换验证码
友情链接