机器学习漏洞大汇总——利用机器学习服务

在本节中,我们将展示机器学习框架中存在的漏洞,这些漏洞会直接处理模型工件,或者通过工件存储或模型注册表的凭证来处理。利用此类漏洞,攻击者可以在企业系统内部进行非常强大的横向移动,从而劫持被利用的模型注册表中的机器学习模型。

WANDB Weave 目录遍历 – CVE-2024-7340

[Weave]是一个用于评估和跟踪大型语言模型 (LLM) 应用程序的工具包,由 Weights & Biases (WANDB) 构建。

Weave 允许从特定目录获取文件,但由于缺乏输入验证,因此也可能通过目录遍历读取整个文件系统的文件。此漏洞已在 Weave 0.50.8 版本中修复。

当 Weave 作为 WANDB 服务器的一部分运行时,通过读取特定文件,该漏洞允许低权限的经过身份验证的用户将其权限升级到管理员角色。

技术细节

Weave Server API 路径 __weave/file/path:path 允许低权限的认证用户从文件系统的特定目录中获取文件。服务器代码旨在检查用户提供的路径是否位于特定目录中,但其逻辑很容易被绕过,从而访问文件系统中的任何文件:

@blueprint.route("/__weave/file/<path:path>")
def send_local_file(path):
    # path is given relative to the FS root. check to see that path is a subdirectory of the
    # local artifacts path. if not, return 403. then if there is a cache scope function defined
    # call it to make sure we have access to the path
    abspath = "/" / pathlib.Path(
        path
    )  # add preceding slash as werkzeug strips this by default and it is reappended below in send_from_directory
    try:
        local_artifacts_path = pathlib.Path(filesystem.get_filesystem_dir()).absolute()
    except errors.WeaveAccessDeniedError:
        abort(403)
    if local_artifacts_path not in list(abspath.parents):
        abort(403)
    return send_from_directory("/", path)

用户提供的路径参数附加到 / 后,并存储在名为 abspath 的变量中。然后,代码检查 abspath 是否以 local_artifacts_path 开头(通过将其与 abspath 的任意父目录进行比较)。

由于代码从未规范化 abspath 变量,因此 abspath 可以包含 …/ 序列以进行目录遍历。

因此,如果 local_artifacts_path 目录是 /some/authorized/path,攻击者可以提供以下路径:some/authorized/path/…/…/…/…/evil/path 以绕过检查,其路径指向 /evil/path 文件。

函数的最后一行将路径传递给 send_from_directory 函数,该函数是一个安全的函数,用于避免目录遍历,详见此处。它不允许在第一个参数指定的目录之外提供文件。但是,当指定的目录是文件系统的根文件夹 (/) 时,它将允许从整个文件系统获取文件,这违背了防止目录遍历的初衷。简而言之,这允许攻击者从文件系统下载(泄露)任何文件。

低权限的经过身份验证的用户可以利用此漏洞,通过从 Weave 服务器泄露名为“api_keys.ibd”的文件,将其权限提升到管理员角色。该文件包含保存明文 API 密钥的 MySQL 数据。如果存在当前有效的管理员 API 密钥,则可以从该文件中提取这些密钥,并用于获取 WANDB 服务器的管理员角色权限。

转储“api_keys.ibd”文件

ZenML Cloud 访问控制不当

ZenML是一个 MLOps 框架,用于创建端到端、可用于生产的机器学习流水线。其基础产品 ZenML Server 可帮助创建机器学习流水线、追踪流水线、模型和工件。ZenML Server大部分是开源的,但其全部功能作为 ZenML Cloud 的一部分提供。ZenML Cloud 是一个基于订阅的平台,支持部署托管的 ZenML 服务器。

我们在 ZenML Cloud 中发现的漏洞允许有权访问托管 ZenML 服务器的用户将其权限从查看者提升到完全管理员权限。ZenML Cloud 平台中的此漏洞在我们负责任地披露后已迅速修复。由于该漏洞存在于云应用程序中,因此未分配 CVE ID。

技术细节

ZenML 云的环境架构允许每个用户创建一个组织对象,该对象包含一组用户,ZenML 服务器实例(称为租户)将存储在该对象中。组织中的每个用户都有一个角色。该角色配置了用户可以查看或修改的内容。

组织所有者可以邀请其他用户加入其组织,但不授予他们对租户的权限,或者仅为特定租户授予较低的权限。

要创建新角色,可以使用 /roles POST API 端点。对此端点的请求包含一个 JSON 结构,其中包含“tenant_id”和“organization_id”字段,以及一个权限列表,每个权限都包含一个“scope”字段,其中包含指向租户 ID 的 UUID。

设想以下场景:一个受害者用户拥有自己的组织和租户。此外,还有一个攻击者,他以受害者租户的低权限(查看者)访问开始,并计划获取受害者租户的管理员权限。

图片[1] - 机器学习漏洞大汇总——利用机器学习服务 - 宋马
ZenML Cloud 中的权限提升攻击场景

为此,攻击者通过向 /roles API 端点发送 POST 请求来创建一个新的管理员角色 – 将(合法)攻击者的组织指定为organization_id,并在权限的tenant_id和scope字段中提供受害者的租户。

POST /roles HTTP/2
Host: cloudapi.zenml.io
...
{
            
  "permissions": [
    {
            
      "resource": {
            
        "scopes": [
          "victim_tenant_uid@server"
        ],
        "type": "secret",
        "id": null
     },
     "action": "read"
    }
 ],
 "system_managed": false,
 "organization_id": "attacker_controlled_organization_uid",
 "tenant_id": "victim_tenant_uid",
 "name": "Tenant_Takeover",
 "description": "Become the admin you deserve to be"
}

对 /roles API 的 HTTP 请求的说明

由于组织权限与租户权限分离,且逻辑上忽略了向其他组织租户添加权限的场景,因此上述请求被接受,新角色成功创建。攻击者随后将这个新角色分配给自己的用户。

现在,当访问受害者的租户时,攻击者拥有租户管理员权限——授予攻击者修改/读取未经授权的组件的能力,包括来自其机密存储和存储的 ML 模型的机密。

后期利用——感染 ML 模型客户端

正如我们在2024 年 BlackHat USA 大会演讲中所讨论的,机器学习模型注册表(以及保存模型的工件库)对于恶意攻击者而言是极高价值的目标。通过劫持机器学习模型注册表,攻击者可以在企业系统内进行横向移动,并轻松创建机器学习模型的后门,从而允许任何客户端(数据科学家、MLOps CI/CD 机器等)在提取和加载这些模型时执行恶意代码。

由于许多 ML 模型格式(包括当今最流行的 ML 模型格式)都支持加载时执行代码,因此加载此类 ML 模型会立即导致代码执行,类似于从 npm 或 PyPI 安装包含安装后脚本的包 –

支持加载时执行代码的模型格式位于顶行,不支持的模型格式位于底行

在上述获取 Weave 服务器管理员权限的场景中,攻击者将能够感染存储在 WANDB 注册表中的机器学习模型,并向其中添加恶意代码层。这些模型随后可能会被下游团队和利益相关者(例如数据科学家或 MLOps CI/CD 机器)使用,这些机器会在机器学习模型加载后立即运行攻击者“附加”的恶意代码。

攻击者通过 ML 注册表漏洞感染多个 ML 客户端

就 ZenML 漏洞而言,获取 ZenML 租户的管理员权限即可访问其机密存储,该存储可能保存其使用的远程工件存储的凭据。此类凭据可能被用于感染组织的机器学习模型或其他 ZenML 腌制工件,这些工件稍后将被客户端加载。

远程劫持机器学习数据库框架

在本节中,我们将介绍两个漏洞——一个是针对 AI 优化的数据库中的漏洞,另一个是使用 LLM 基于自然语言生成 SQL 查询的框架中的漏洞。

Deep Lake 数据库命令注入 – CVE-2024-6507

Deep Lake是一款针对 AI 优化的数据库。它可用于在构建 LLM 应用程序时存储数据和向量,或在训练深度学习模型时管理数据集。

Kaggle是一个托管机器学习数据集、模型和代码片段的公共存储库。此漏洞允许攻击者在上传远程 Kaggle 数据集时注入系统命令。

由于使用潜在危险函数运行操作系统命令时未进行适当的输入清理,导致此漏洞。此漏洞已在 3.9.11 版本中修复。

技术细节

数据集可以从各种外部来源加载,例如 Kaggle 平台。为了加载外部 Kaggle 数据集,用户可以使用导出的 ingest_kaggle 方法:

@staticmethod
def ingest_kaggle(
    tag: str,
    ...
) -> Dataset:
    # ...
    download_kaggle_dataset(
        tag,
        local_path=src,
        kaggle_credentials=kaggle_credentials,
        exist_ok=exist_ok,
)
# ...

该方法接收一个 tag 参数,该参数指示 Kaggle 数据集的标签名称。
该 tag 参数会传递到 download_kaggle_dataset 方法中:

def download_kaggle_dataset(
     tag: str,
     ...
):
     # ...
     _exec_command("kaggle datasets download -d %s" % (tag))
     # ...

这里我们可以看到标签参数传递到 _exec_command 方法中,没有任何形式的输入过滤:

def _exec_command(command):
    out = os.system(command)
    # ...
 

不安全的 os.system 函数在子 shell 中执行其命令,允许执行链式 OS 命令,如 command1 || command2,这可能导致在操作系统上执行代码。

简而言之,任何能够向 ingest_kaggle API 提供任意标签的攻击者都可以触发任意 shell 命令。最糟糕的情况是远程代码执行,例如在某个 Web 应用程序中,该应用程序允许用户通过指定标签将任意 Kaggle 数据集导入 Deep Lake 数据库。

Vanna.AI 提示注入代码执行 – CVE-2024-5565

Vanna AI 是一个基于 Python 的库,旨在简化使用 LLM 从自然语言输入生成 SQL 查询的过程。Vanna AI 的主要目的是促进文本到 SQL 的精确转换,使用户无需具备丰富的 SQL 知识即可更轻松地与数据库交互。Vanna AI 支持多种交付机制,包括 Jupyter 笔记本、Streamlit 应用程序、Flask Web 服务器和 Slack 机器人,从而为用户部署和使用该工具的方式提供了灵活性。

我们发现的漏洞是一个利用即时注入技术的远程代码执行漏洞,该漏洞允许我们执行代码。这是一个影响LLM的“即时注入”攻击示例,如果该攻击导致代码执行,将会产生严重后果。

背景:预提示和提示注入

开发人员使用硬编码指令,这些指令将添加到每个用户提供的提示(对 LLM 的聊天查询)中,并为 LLM 提供更多关于如何处理查询的背景信息,以避免负面意见、粗言秽语以及任何不受欢迎的内容。

LLM 没有控制平面和数据平面之间的区别,并且“一切都是输入”,这意味着即使是预定义的提示指令也被视为与用户输入的提示相同。因此,每个用户输入都可以操纵提示的上下文,从而扭曲或破坏所有预定义的提示指令,这是一个“设计缺陷”。

使用预先提示指令来控制 LLM 输出

独立注射与集成快速注射

虽然即时注入可能导致生成有害、误导或禁用内容,但如果 LLM 未连接到任何可操作的系统或流程,则注入对系统造成的风险相对有限。由于无法直接执行命令、做出决策或影响实际操作,潜在损害仅限于生成的文本本身。但是,如果 LLM 直接与命令执行或决策相关,则可能导致严重的安全问题。

漏洞

我们在 Vanna.AI 中发现的漏洞是一种集成提示注入,涉及查询结果可视化功能。执行 SQL 查询(基于用户的自然语言)后,Vanna 库可以使用基于 Python 的图形库 Plotly 将结果以图表形式呈现。

使用 Plotly 的 Python 代码并非静态的,而是通过 LLM 提示和代码评估动态生成的。这最终使我们能够使用智能提示来操纵 Vanna.AI 预定义的约束,从而实现任意 Python 代码执行。

使用 Vanna.AI 可视化功能时的提示流程

简而言之,能够通过 Vanna.AI 发布任意查询的攻击者,还可以在使用 Vanna.AI 库的主机上实现远程代码执行——

使用 Prompt Injection 在 Vanna.AI 中实现 RCE

有关 Vanna.AI 漏洞的更多详细信息,请阅读我们的博客。

后利用——数据库渗漏和操纵

在上述两种情况下,攻击者都可以劫持直接访问数据库的机器。在 Deep Lake 的案例中,该数据库保存着支持 LLM 应用程序或帮助训练 ML 模型的数据。泄露这些数据可能会造成重大的知识产权损失,或者对某些公司(例如 OpenAI,其 GPT 模型每年创造数十亿美元的收入)造成重大损失,修改这些数据可能会导致 ML 中毒攻击,导致 LLM 应用程序返回不需要的或恶意的信息。

通过数据集毒害机器学习模型

在 Vanna.AI 的案例中,该库连接到通用 SQL 数据库,这意味着泄露或毒害它的影响取决于数据库中存储的具体内容。

远程劫持机器学习管道

法师AI多个漏洞

Mage 是一款用于转换和集成数据的开源数据管道工具。例如,它允许用户构建管道,用于转换从标准 API 接收的数据并将其导入到知名数据库;或者构建管道,用于加载数据集并训练新的机器学习模型。我们在 Mage 平台中发现了多个漏洞。

通过已删除用户进行未经授权的 Shell 访问 – CVE-2024-45187

Mage Web UI 提供多种功能。其中之一就是终端,允许 Shell 访问运行 Mage 的机器。与 Shell 的通信通过 WebSocket 完成。

在terminal_server.py的message函数中,代码接收来自终端客户端的消息。然后,该代码负责检查用户身份验证令牌,并将接收到的命令发送到终端。

代码首先检查 API 密钥,该密钥始终相同:

zkWlN0PkIKSN0C11CfUHUj84OT5XOJ6tDZ6bDRO2。

即使不同,由于 Web 服务器的前端一直在使用它,因此即使不登录也很容易检索。然后,代码会检查客户端发送的令牌的有效性。如果令牌有效,则将 valid 变量设置为 True。然后,如果有与该令牌关联的用户,代码会检查用户的角色并相应地设置 valid 变量。之后,如果 valid 变量为 True,则将消息发送到终端。

由于在检查令牌是否与用户关联之前,valid 变量被设置为 True,因此可能存在有效令牌未与任何用户关联的情况,从而允许命令直接到达终端。这种情况最有可能发生在用户被删除时。

例如,如果删除了低权限用户(最初没有 Shell 访问权限),该用户的身份验证令牌仍会缓存在数据库中,默认有效期为创建后的 30 天。如果该用户再次使用其身份验证令牌,则将被授予 Mage Web 终端的访问权限,并可以在托管 Mage.AI 的服务器上运行任意命令。

远程任意文件泄漏 – CVE-2024-45188、CVE-2024-45189、CVE-2024-45190

Mage.AI 的部分服务器 API 存在路径遍历漏洞。file.py 文件中的函数Ensure_file_is_in_project负责检查文件是否位于项目文件夹中。当平台配置为多项目平台时,该函数会直接返回,而不会检查路径。

该函数在多个地方使用,但最有趣的是该函数由成员函数调用,低权限(查看者)用户可以访问该函数。

此用法在FileContentResource.py 文件中。这可以允许经过身份验证的低权限用户通过向配置为多项目平台的 mage 平台上的路径 /api/file_contents/<PATH_TO_LEAK> 发送 GET 请求来读取系统上的任何文本文件。

此外, GitFileResource.py 中的成员函数接收一个文件路径,以便从 Git 仓库读取。该函数不检查路径遍历,因此任何具有“查看者”角色的用户都可以通过向路径 /api/git_file/<PATH_TO_LEAK> 发送 GET 请求来读取系统中的文本文件。由于这些文件以 utf-8 编码打开,因此无法读取二进制文件。

最后, InteractionResource.py 中的成员函数接收一个交互式通用唯一标识符(UUID)。代码使用该 UUID 创建一个新的 Interaction 对象。UUID 最终会作为文件名被读取并返回给客户端。代码不会检查路径遍历,因此任何具有“查看者”角色的用户都可以通过向路径 /api/pipelines/example_pipeline/interaction/<PATH_TO_LEAK> 发送 GET 请求来读取系统上的文本文件。

后期利用——ML管道操作

所有上述漏洞都可能导致在 Mage.AI 服务器上执行远程代码。未经授权的 Shell 访问漏洞将直接导致 root 权限的远程代码执行,因为攻击者拥有 root 权限的远程 Shell 访问权限。任意文件泄露漏洞也可能导致远程代码执行,但需要攻击者在 Mage.AI 服务器上针对每个目标进行研究。例如,泄露(并破解)具有远程 SSH 访问权限的用户的密码可能导致远程代码执行。

一旦实现代码执行,攻击者将能够控制由这些框架管理的 ML 管道。

常见 MLOps 管道的步骤

由于 MLOps 管道可能有权访问组织的ML 数据集、ML 模型训练和 ML 模型发布,因此利用 ML 管道可能导致极其严重的数据泄露。本博客中提到的每种攻击(ML 模型后门、ML 数据中毒等)都可能由攻击者执行,具体取决于 MLOps 管道对这些资源的访问权限。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容