利用ML模型的Pickle文件攻击:第二部分
在第一部分中,我们介绍了Sleepy Pickle攻击,该攻击利用恶意pickle文件 stealthily 破坏ML模型并对终端用户实施复杂攻击。本文展示如何调整该技术以在受感染系统上实现持久存在且不被检测。这种变体技术我们称之为Sticky Pickle,它包含自复制机制,将恶意负载传播到受损模型的后续版本中。此外,Sticky Pickle使用混淆技术伪装恶意代码,防止被pickle文件扫描器检测。
实现恶意Pickle负载的持久化
回顾我们之前的博客文章,Sleepy Pickle攻击依赖于将恶意负载注入包含打包ML模型的pickle文件中。该负载在pickle文件反序列化为Python对象时执行,破坏模型的权重和/或相关代码。如果用户决定修改受损模型(例如微调)然后重新分发,它将被序列化为攻击者无法控制的新pickle文件。此过程很可能使攻击失效。
为克服此限制,我们开发了Sticky Pickle,一种自复制机制,将我们的模型破坏负载封装在持久化负载中。封装负载在执行时执行以下操作:
- 在本地文件系统中查找正在加载的原始受损pickle文件。
- 打开文件并从磁盘读取封装负载的字节。(负载无法通过其自己的Python代码直接访问它们。)
- 在预定义属性名称下,将自身字节码隐藏在正在反序列化的对象中。
- 挂钩pickle.dump()函数,以便在对象重新序列化时:
- 使用常规pickle.dump()函数序列化对象。
- 检测对象是否包含字节码属性。
- 手动将字节码注入刚刚创建的新Pickle文件中。
图1:恶意ML模型文件中的持久化负载
通过此技术,恶意pickle负载自动传播到派生模型,而不会在受感染pickle文件之外的磁盘上留下痕迹。此外,挂钩Python解释器中任何函数的能力允许其他攻击变体,因为攻击者可以访问其他本地文件,如训练数据集或配置文件。
负载混淆:规避检测
基于pickle的攻击的另一个限制源于恶意负载直接作为Python源代码注入。这意味着恶意代码以明文形式出现在Pickle文件中。这有几个缺点。首先,可以通过简单的文件扫描和一些针对Pickle文件中原始Python大块存在的启发式方法检测攻击。其次,安全团队只需查看即可轻松识别攻击及其意图。
我们开发了一种负载混淆和编码方法,克服了这些限制并使负载检测更加困难。从我们原始的破坏pickled ML模型的代码负载开始,我们通过两种方式修改它。
首先,我们通过将负载编译为Python代码对象并使用marshal库将其序列化为字符串来混淆负载。这使我们能够将此序列化负载字符串注入pickle文件,后跟一个特殊的字节码序列。执行时,此特殊序列对字符串调用marshal.loads()以重建负载的代码对象并执行它。这使得负载对扫描器或人工检查完全不可读,因为它作为编译的Python字节码而不是源代码注入。
其次,我们使用简单的XOR编码在每个受感染文件中变化负载。XORed负载不仅包含原始模型破坏代码,还包含原始负载的XOR编码Python源代码以及类似于以下的解码和执行存根:
|
|
由于混淆密钥可以取任何值并在解码存根中硬编码,此方法通过允许攻击者编写在新pickle文件中重新注入时生成新混淆密钥的负载来补充持久性功能。这导致不同的Python负载、代码对象和最终pickle负载被注入到受损文件中,而恶意行为保持不变。
图2:在注入pickle文件之前Python负载的混淆
图2显示此混淆方法如何完全隐藏文件中的恶意负载。扫描文件的自动化工具或安全分析师只会看到:
- Python负载的原始字节,这些字节被编译然后marshalized。解释这些字节并将其标记为危险对于静态扫描来说很困难,甚至不可能。
- 调用marshal.loads()的pickle序列。这是一种常见模式,也存在于良性pickle文件中,因此不足以警告用户潜在的恶意行为。
当加载包含混淆负载的pickle文件时,负载阶段按以下顺序执行,如图3所示:
- 恶意pickle操作码加载序列化代码对象的原始字节,然后使用marshal.load()重建Python代码对象,最后执行代码对象。
- 代码对象执行并解码原始负载的XOR编码Python源代码。
- 解码的原始负载代码执行并破坏加载的ML模型。
图3:混淆负载执行阶段概述
封存Pickle的风险
这些持久化和规避技术展示了pickle攻击可以达到的复杂程度。扩展我们在本系列第一部分中展示的关键风险,我们看到了单个恶意pickle文件如何:
- 破坏其他本地pickle文件和ML模型。
- 规避文件扫描并使手动分析 significantly harder。
- 使其负载多态化并以不断变化的形式传播,同时保持相同的最终阶段和最终目标。
虽然这些只是其他可能攻击改进中的示例,但持久化和规避是pickle攻击的关键方面,据我们所知,尚未得到演示。
尽管pickle文件带来风险,我们承认ML生态系统的主要框架远离它们将是一项长期努力。短期内,您可以采取以下行动步骤来消除对这些问题的暴露:
- 避免使用pickle文件分发序列化模型。
- 采用更安全的pickle文件替代方案,如HuggingFace的SafeTensors。
- 另请查看我们对SafeTensors的安全评估!
- 如果必须使用pickle文件,请使用我们自己的Fickling扫描它们以检测基于pickle的ML攻击。
长期来看,我们继续努力推动ML行业采用安全设计技术。如果您想了解更多关于我们的贡献,请查看我们的awesome-ml-security和ml-file-formats Github仓库以及我们最近对称为Leftover Locals的关键GPU漏洞的负责任披露!
致谢
感谢我们的实习生Russel Tran在pickle负载混淆和优化方面的辛勤工作。
如果您喜欢这篇文章,请分享: Twitter LinkedIn GitHub Mastodon Hacker News
页面内容 近期文章 使用Deptective调查您的依赖项 系好安全带,Buttercup,AIxCC的评分回合正在进行中! 使您的智能合约成熟超越私钥风险 Go解析器中意想不到的安全隐患 我们从审查首批DKLs23库中学到的东西 来自Silence Laboratories的库 © 2025 Trail of Bits. 使用Hugo和Mainroad主题生成。