Hugging Face 任意大模型仓库劫持 - 无声的破坏

图片

摘要

在这篇博客中,我们展示了攻击者如何攻击Hugging Face的Safetensors转换空间及其相关的服务机器人。这些服务是一个在Hugging Face上广受欢迎的服务,专门用于将不安全的机器学习模型转换为更安全的版本。我们随后展示了如何通过Hugging Face自身的服务,发送带有攻击者控制数据的恶意拉取请求到平台上的任何仓库,以及如何劫持通过转换服务提交的任何模型。我们使用一个被劫持的模型来证明了这一点,这个模型是设计用来测试转换服务的,该服务允许攻击者通过冒充Hugging Face转换机器人来请求对平台上的任何仓库进行更改。我们还展示了如何可能在服务中持久化恶意代码,以便在模型转换时自动劫持模型。

尽管转换服务的代码在Hugging Face服务器上运行,但系统是在Hugging Face Spaces中容器化的 — 这是一个平台,任何用户都可以在其中运行代码。因此,大部分风险不是针对Hugging Face本身,而是针对托管在该网站上的仓库及其用户。我们的团队感到有义务将这项研究公之于众,以便在造成任何损害之前找到任何可能被破坏的模型。在我们的公开报告漏洞之后,我们还联系了Hugging Face,以便在发布之前给他们时间关闭转换服务或实施安全措施。

介绍

任何人工智能系统的核心都是一个机器学习模型 — 是在给定数据集上进行大量计算的结果,经过训练、调整和优化,以执行特定任务或一般的应用程序。在模型可以部署到产品中或作为服务的一部分使用之前,它必须被序列化(保存)到磁盘上,这被称为序列化格式。通过有效地将模型简化为二进制表示,我们可以在它被训练的系统之外部署模型,或者与我们希望的任何人共享。在行业中,这些模型通常被称为“预训练模型”,并且它们已经风靡全球。

预训练的开源模型是人工智能广泛采用的主要推动因素之一,使数据科学团队能够共享、下载和重用现有模型,以适应他们的特定应用程序,而无需从头开始创建所需的庞大资源。事实上,模型的共享已经变得如此普遍,以至于围绕这一前提创建了公司。Hugging Face拥有一个强大的社区,迄今为止已经上传了超过500,000个预训练模型到平台。

模型即代码

如果您一直在关注我们的研究,您会知道模型其实就是代码,一些广泛使用的序列化格式在某种程度上允许执行任意代码,并且正在被野外利用。最大的罪魁祸首是Pickle,尽管它是最脆弱的序列化格式,但却是最广泛使用的。Pickle是PyTorch库的基础,并且是Hugging Face上最普遍的序列化格式。

为了缓解由易受攻击的序列化格式带来的供应链风险,Hugging Face团队开始开发一种新的序列化格式,这种格式从一开始就以安全为考虑构建,以便不能用于执行恶意代码 — 他们称之为Safetensors。

理解转换服务

Safetensors正如其名,允许安全的反序列化机器学习模型,主要是因为它只存储模型权重/偏移,而不存储可执行代码。为了帮助用户基础转向这个更安全的替代方案,公司创建了一个转换服务,通过拉取请求将仓库中的任何PyTorch模型转换为Safetensors版本。转换服务的代码(convert.py)直接来自Safetensors项目,并通过Hugging Face Spaces运行,这是一个在浏览器中运行Python代码的云计算产品。

在这个空间中,一个Gradio应用程序与convert.py捆绑在一起,提供了一个Web界面,用户可以在其中指定要转换的仓库。该应用程序只允许针对PyTorch二进制文件进行转换,并要求仓库中存在名为pytorch_model.bin的文件才能启动转换过程,如下图所示:

图片

要转换的huggingface存储库

用户可以导航到转换服务的Web界面,并以以下格式输入仓库ID:

<用户名>/<仓库名称>

对于我们的测试,我们创建了以下仓库,其中包含我们特别制作的PyTorch模型:

图片

转换服务Web UI

如果用户提供了一个包含可解析PyTorch模型的有效仓库,并且格式正确,转换服务将转换模型,并通过‘SFconvertbot’用户在原始仓库中创建拉取请求。下图中显示的过程的第一步,我们不需要输入目标仓库所有者的用户提供的令牌,这意味着我们可以向任何项目提交转换请求,即使这些项目不属于我们。

图片

SafeTensors 转换机器人“SFconvertbot”向存储库发出拉取请求

识别攻击向量

我们对转换机器人如何加载PyTorch文件感到好奇,因为一个简单的torch.load()调用就足以危害宿主机器。可以看到在convert.py中,有一个安全警告,必须在命令行直接运行时手动确认(而不是通过捆绑的Gradio应用程序app.py):

图片

convert.py 安全警告

出乎意料的是,其张量确实是使用torch.load()函数加载的,如果PyTorch模型中存储了恶意代码,这可能导致任意代码执行。我们猜测是否在Hugging Face Spaces中的转换机器人有什么不同呢?事实证明,并没有什么不同!

图片

convert.py 转换脚本中使用的 torch.load()

在这一点上,我们意识到。是否可以利用它设计的转换功能进而劫持托管转换服务呢?

制作攻击载荷

我们开始将我们的想法付诸实践,通过制作一个恶意的PyTorch二进制文件,使用预训练的AlexNet模型,并注入我们的第一个payload  eval("print('hi')") 一个简单的eval调用,会打印出'hi'。

我们没有在实时服务上进行测试,而是部署了一个本地版本的转换服务来评估我们的代码执行能力,并查看是否会创建拉取请求。

我们能够确认我们的模型已经被加载,因为我们可以看到输出中的'hi',但有一个奇怪的错误。似乎通过添加我们的利用代码,我们改变了模型的文件大小超过了1%,这最终阻止了模型的转换或机器人创建拉取请求:

图片

本地运行 convert.py 的终端输出

面对这个错误,我们考虑了两种可能的方法来规避问题。要么使用一个更大的模型文件,要么通过某种方式来绕过大小检查。由于我们希望我们的利用能够在任何类型的PyTorch模型上工作,我们决定采用后者,并分析文件大小检查的逻辑。

图片

check_file_size函数

起初,我们想要找到一个可行的方法来修改文件大小以跳过条件逻辑。然而,当PyTorch模型被加载时,Safetensors文件还不存在,导致了错误。但由于我们的恶意模型在文件大小检查之前就已经加载了,因此我们可以在运行时动态修改convert.py脚本,并重写函数指针,以便调用不同的函数而不是check_file_size。

由于check_file_size没有返回任何内容,我们只需要一个接受两个字符串并且不抛出异常的函数。我们的潜在替代函数os.path.join完美地符合这个标准。然而,当我们尝试重写函数时,我们发现了一个问题。PyTorch不允许在任何字符串中使用等号'=',这阻止了我们以这种方式为函数指针赋值。为了应对这一点,我们创建了以下payload,使用setattr来手动重写函数指针:

图片

用于覆盖 check_file_size 函数指针的 Python 代码

在对我们的PyTorch模型进行了上述payload修改后,我们就能够使用我们的本地转换器成功转换模型。此外,当我们通过Hugging Face的转换器运行模型时,我们能够成功创建拉取请求,现在就有了破坏托管转换机器人的系统的能力:

图片

成功转换恶意 PyTorch 模型并使用 Hugging Face 服务发出拉取请求

模仿是最好利用

虽然在沙箱中任意执行代码已经危害很大,但我们注意到了一个更大的威胁。转换服务生成的所有拉取请求都是通过SFconvertbot发出的,这是一个专门为此目的的官方机器人。如果一个不知情的用户看到一个来自机器人的拉取请求,声称他们的模型有安全更新,他们可能会接受更改。这可能允许我们上传不同的模型来替换他们希望转换的模型,从而植入后门,或完全更改模型——构成巨大的供应链风险。

由于我们知道机器人是在与convert代码运行在相同的沙箱中创建拉取请求的,我们也知道机器人的凭证很可能也在沙箱里。

分析代码时,我们看到它们被设置为环境变量,并且可以使用os.environ.get("HF_TOKEN")访问。虽然我们现在有了访问令牌的权限,但我们仍然需要一种方法来窃取它。由于容器必须下载文件并创建拉取请求,我们知道它会有一定的网络访问权限,所以我们决定测试一下。为了确定我们是否可以访问Hugging Face域空间之外的域,我们创建了一个远程webhook,并通过恶意模型向钩子发送了一个get请求:

图片

从运行Hugging Face转换服务的系统接收Web请求

成功了!我们现在有办法窃取Hugging Face SFConvertbot令牌,向网站上的任何仓库发送恶意拉取请求,冒充合法的官方服务。

但我们还没有完成。

你无法打败真实的东西

我们不满意仅仅模仿机器人,我们决定检查服务是否在每次用户尝试转换模型时重新启动,以评估留下持久性后门的机会。为了实现这一点,我们创建了我们自己的Hugging Face Space,基于Gradio SDK,使我们的空间尽可能接近转换服务。

图片

在创建我们自己的测试空间时选择 Gradio SDK 选项

现在我们已经设置好了空间,我们需要一种方法来模仿转换过程。我们创建了一个Gradio应用程序,它接受用户输入,并使用内置的Python函数'exec'执行它。

然后,我们包含了一个名为'greet_world'的虚拟函数,无论用户输入什么,都会输出'Hello world!'。这让我们能够非常接近地模拟转换函数的环境,允许我们以类似于torch.load()调用的方式执行代码,并给我们一个目标函数来尝试在运行时覆盖。我们真正的目标是convert.py中的save_file函数,它负责将转换后的SafeTensors文件保存到磁盘。

图片

我们来自 Hugging Face Spaces 的测试代码

在设置好并运行起来后,我们进行了一个简单的测试,看看应用程序在执行一些代码后是否会返回“Hello World”。

图片

我们在自己的空间中测试的Gradio应用程序

我们采用了与绕过get_file_size函数类似的方法,尝试使用setattr覆盖greet_world。在我们的利用脚本中,我们限制了自己只能在torch.load()的上下文中允许使用的内容。我们决定采用创建一个本地文件方式,将我们想要的代码写入其中,获取一个指针,并用我们自己的恶意函数替换它的方法。

图片

我们成功覆盖了greet_world函数

正如上图所示,响应从“Hello World!”变为了“pwned”,这是我们的成功佐证。现在真正的测试开始了。我们必须看看一旦我们在浏览器中刷新了空间,我们对空间所做的更改是否会持久生效。通过这样做,我们可以看到实例是否会重新启动,以及我们的更改是否会持久。再次,我们输入了最初的良性提示,但这一次,我们新刷新的页面上的结果依然是“pwned”。我们实现了持久性。

图片

我们对受损空间进行提示测试。

我们已经证明了,攻击者可以在任何人尝试转换他们的模型时运行任何任意代码。用户自己没有任何迹象,他们的模型可能在转换时被劫持。更重要的是,如果用户希望转换他们自己的私有仓库模型时,我们可以有效地窃取他们的Hugging Face令牌,破坏他们的仓库,并查看该用户可以访问的所有私有仓库、数据集和模型。请注意:在进行这项研究时,我们没有泄露SFConvertbot令牌,也没有对Hugging Face系统进行恶意操作。我们相信发现漏洞是为了修复它们,一旦我们确认了我们的发现,就会立即停止。

这意味着什么

Hugging Face的用户范围囊括了个人研究者到核心组织,他们上传模型供社区自由使用。平台上上传的50w+个机器学习模型中的许多都容易受到不安全文件格式的恶意代码注入。为了遏制这一点,Hugging Face引入了Safetensors转换机器人,任何用户都可以将他们的模型转换为一个更安全的替代方案,免受恶意软件的影响。然而,我们展示了这个过程如何被劫持,并公开质疑这项服务是否可能已经被利用,可能导致重大的供应链风险,其中很多组织已经接受了这个机器人对他们模型的建议更改。

我们已经确定了像Microsoft和Google这样的组织,他们共同在Hugging Face上托管了905个模型,作为可能面临针对性供应链攻击的风险,因为他们接受了这个机器人对他们Hugging Face仓库的一些更改。任何作为拉取请求的一部分创建的更改都被视为来自受信任的Hugging Face关联机器人,因此通常不会受到质疑。虽然用户可以要求转换他们自己的仓库,但这并不一定要起源于该用户 — 任何用户都可以为公共仓库提交转换请求,这将导致机器人在相关仓库中创建拉取请求。

如果攻击者愿意,他们可以使用上述的方法创建原始模型的自己的版本,并植入后门以触发恶意行为,例如绕过面部识别系统或生成虚假信息。比较机器学习模型之间的更改需要仔细审查,因为模型本身是非人类可读格式存储,这意味着比较它们的唯一方法是程序化的,靠肉眼比较将不起作用。因此,在Hugging Face上接受拉取请求时,并不知道模型是否已被劫持或更改。因此,我们建议您彻底调查您控制的任何仓库,以确定是否有任何非法篡改您的模型权重和偏差,作为这种不安全的转换过程的结果。

图片

一个Google仓库,该仓库接受了来自Hugging Face SFconvertbot的唯一接受的拉取请求

正如上图所示,Google的vit-base-patch16-224-in21k模型接受了来自SFConvertbot的拉取请求,并拒绝了另一个试图更改README的拉取请求。在下面的图中,我们可以看到,仅在过去一个月,该模型就被下载了3,836,972次。虽然我们还没有在这个模型中检测到任何被攻击的迹象,但这证明了即使是最大的组织也对转换服务寄予了隐含的信任。

图片

同一个Google仓库在过去一个月中下载了3,836,972次

结论

通过恶意的PyTorch二进制文件,我们展示了如何可能破坏Hugging Face的Safetensors转换服务。同时展示了如何窃取官方Safetensors转换机器人的令牌,代表其向网站上的任何仓库提交拉取请求。我们还展示了攻击者如何接管服务,以自动劫持提交给服务的任何模型。

这种攻击的潜在后果是巨大的,因为对手可以植入自己的模型,将恶意模型推送到仓库中,或访问私有仓库和数据集。在已经转换的仓库的情况下,我们仍然可以提交新的拉取请求,或者在该仓库上传并使用受损的转换服务转换的新PyTorch二进制文件的情况下,去影响那些下载量达到数十万的仓库。

尽管Hugging Face生态系统中保护机器学习模型的初衷是最好的,但转换服务已被证明是脆弱的,并有可能通过Hugging Face官方服务引发广泛的供应链攻击。此外,我们还展示了攻击者如何获得运行服务的容器的权限,并破坏由服务转换的任何模型。

沙箱化是锁定应用程序的一个很好的方式,如果您担心机器上可能存在代码执行的话。然而,即使在沙箱化的情况下,也不应该允许任意代码在执行重要社区服务的同一应用程序中运行。我们理解处理已知的代码执行方法(如Pickle/PyTorch文件格式)可能会很棘手,这就是为什么我们是扫描机器学习模型以查找恶意内容的坚定支持者。

在Google和Microsoft的前10个最多下载模型中,接受机器人转换过的模型在过去一个月中下载量达到了惊人的16,342,855次。虽然这20个模型只是Hugging Face上托管的500,000多个模型的一小部分,但它们触达了惊人的用户数量,让我们不禁思考,考虑到机器人已经做了42,657次模型转换,有多少用户下载了可能恶意的模型?

来源:hiddenlayer

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

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

相关文章

GoogleNet原理与实战

在2014年的ImageNet图像识别挑战赛中&#xff0c;一个名叫GoogLeNet 的网络架构大放异彩。以前流行的网络使用小到11&#xff0c;大到77的卷积核。本文的一个观点是&#xff0c;有时使用不同大小的卷积核组合是有利的。 回到他那个图里面你会发现,这里的一个通过我们最大的池化…

《Linux从小白到高手》理论篇:Linux用户和组相关的命令

List item 本篇介绍Linux用户和组相关的命令&#xff0c;看完本文&#xff0c;有关Linux用户和组相关的常用命令你就掌握了99%了。Linux用户和组相关的命令可以分为以下六类&#xff1a; 一.用户和用户组相关查询操作命令&#xff1a; Id id命令用于显示用户的身份标识。常见…

职场中的10个“人情世故”,随处可见

职场上&#xff0c;“现实”是主基调。如果不通#人情世故#&#xff0c;可能举步维坚。很多时候&#xff0c;人情世故并不是什么高深的学问&#xff0c;就是在点点滴滴间&#xff0c;只要稍加注意&#xff0c;就能学通。下面这10条&#xff0c;是职场很常见的人情世故。 1、登门…

InnoDB 事务模型

文章目录 InnoDB 事务模型事务ACID特性事务隔离级别 事务操作事务并发问题事务数据读写类型Consistent Nonlocking Reads 快照读Locking Reads 加锁读 MVCC 并发控制实现原理InnoDB 隐藏列Read ViewUndo log实现过程 MVCC与隔离级别MVCC和辅助索引 幻读幻行问题可重复读MVCC会出…

HTB:Synced[WriteUP]

目录 连接至HTB服务器并启动靶机 1.What is the default port for rsync? 2.How many TCP ports are open on the remote host? 3.What is the protocol version used by rsync on the remote machine? 4.What is the most common command name on Linux to interact w…

一些关于上传数据-p7zip-full-压缩包的经验

目录 前言 7z 简介 Windows如何压缩tar.gz格式 一、下载7-ZIP 二、tar文件进一步压缩 说明&#xff1a; 前言 本人每次在linux服务器上执行apt-get install p7zip-full命令&#xff0c;都会有复杂依赖报错&#xff08;因为实验过程中用到的依赖包太多了&#xff09;&…

[Python学习日记-39] 闭包是个什么东西?

[Python学习日记-39] 闭包是个什么东西&#xff1f; 简介 闭包现象 闭包意义与作用 简介 在前面讲函数和作用域的时候应该提到过&#xff0c;当函数运行结束后会由 Python 解释器自带的垃圾回收机制回收函数内作用域已经废弃掉的变量&#xff0c;但是在 Python 当中还有一种…

Linux中的多线程

Linux线程概念 在一个程序里的一个执行路线就叫做线程&#xff08;thread&#xff09;。更准确的定义是&#xff1a;线程是“一个进程内部的控制序 列” 进程是系统分配资源的基本实体 线程是CPU调度的基本单位 POSIX线程库 创建线程 功能&#xff1a;创建一个新的线程 原…

Tkinter打包成EXE安装文件

打包成 .exe可执行文件 1. 安装PyInstaller&#xff0c;命令如下&#xff1a; pip install pyinstaller2. 编写你的Tkinter应用程序&#xff1a; 创建一个Python文件&#xff0c;例如app.py&#xff0c;并写入你的Tkinter代码。 3. 在 app.py 文件所在的目录使用PyInstaller…

从零开始讲PCIe(5)——66MHZ的PCI总线与其限制

一、前言 在之前的内容中&#xff0c;我们已经基本了解了PCI总线的设计思路和传输机制&#xff0c;之前的内容我们都是基于33MHZ版本的PCI总线进行学习的&#xff0c;为了支持更到的带宽&#xff0c;PCI协议还有一种66MHZ的版本。 二、高带宽PCI&#xff08;66MHZ&#xff09;…

UML类图全解析

1.UML的基本介绍 1.1什么是UML 1.UML > 统一建模语言&#xff0c;是一种用于软件系统分析和设计的语言工具&#xff0c;它用于帮助软件开发人员进行思考和记录思路的结果。 2.UML本身是一套符号的规定&#xff0c;就像数学符号和化学符号一样&#xff0c;这样符号用于描述软…

dll动态库加载失败导致程序启动报错以及dll库加载失败的常见原因分析与总结

目录 1、问题说明 2、dll库的隐式加载与动态加载 2.1、dll库的隐式加载 2.2、dll库的显式加载 3、使用Process Explorer查看进程加载的dll库信息以及动态加载的dll库有没有加载成功 3.1、使用Process Explorer查看进程加载的dll库信息 3.2、使用Process Explorer查看动态…

交叠型双重差分法

交叠型双重差分法&#xff08;Staggered Difference-in-Differences, Staggered DiD&#xff09;是一种扩展的双重差分&#xff08;Difference-in-Differences, DiD&#xff09;方法&#xff0c;用于处理多个时间点的政策干预或处理组&#xff08;treatment group&#xff09;并…

JavaWeb的小结02

第2章-第2节 一、知识点 HttpServletRequest请求对象、HttpServletResponse响应对象、响应内容类型Content-Type、请求转发、重定向、ServletContext对象。 二、目标 深刻理解HttpServletRequest对象的作用。 深刻理解HttpServletResponse对象的作用。 掌握HttpServletRequ…

企业必备:搭建大模型应用平台实操教程

最近AI智能体很火&#xff0c;AI智能体平台化产品肯定属于大公司的。但在一些场景下&#xff0c;尤其是对业务数据要求很高的公司&#xff0c;那就只能用私有大模型。不一定完全是为了对外提供服务&#xff0c;对内改造工作流也是需要的。所以 我感觉未来大部分企业都会搞一个…

普渡PUDU MT1:AI赋能,破解大面积场景清洁新挑战

普渡AI智能扫地机器人PUDU MT1:破解大面积场景清洁难题的新利器 在仓储物流、工业车间、交通枢纽、大型商场等大面积场景中,清洁难题一直是管理者们头疼的问题。这些区域面积广阔,清洁任务繁重,传统清洁方式难以胜任。然而,普渡机器人最新推出的AI智能扫地机器人PUDU MT1…

什么是 HTTP Get + Preflight 请求

当在 Chrome 开发者工具的 Network 面板中看到 GET Preflight 的 HTTP 请求方法时&#xff0c;意味着该请求涉及跨域资源共享 (CORS)&#xff0c;并且该请求被预检了。理解这种请求的背景&#xff0c;主要在于 CORS 的工作机制和现代浏览器对安全性的管理。 下面是在 Chrome …

ConcurrentHashMap在JDK1.7和1.8的区别,详解

目录 1.了解HashMap底层插入原理 2.ConcurrentHashMap 是什么&#xff1f; HashTable的实现 3.ConcurrentHashMap 1.7和1.8的区别 4、JDK1.7 中的ConcurrentHashMap实现原理 6、JDK1.8中的ConcurrentHashMap 7.链表转红黑树条件 1.8 put方法 8.并发扩容 9.总结 首先呢…

Origin正态分布检验

在spass中用Shapiro-Wilk检验--正态分布检测 Shapiro-Wilk检验--正态分布检测_spss shapiro-wilk检验-CSDN博客

数据服务-实时同步(sersync)

1. 概述 1.之前我们通过rsync定时任务实现定时备份/同步 2. 对于NFS我们需要进行实时同步 2. Sersync原理 3. 上手指南 环境主机web0110.0.0.7(nfs客户端)nfs0110.0.0.31(rsync客户端) (nfs服务端)backup10.0.0.41(rsync服务端) 3.1 rsync服务端准备 参考: 数据服务-备份服务…