如何在 Python 中安全地反序列化 pickle 文件防止恶意代码执行?

文章导读
在 Python 中安全地反序列化 pickle 文件的核心原则是绝对不要对不可信来源的数据进行 unpickle 操作。为了防止恶意代码执行,开发者应优先使用更安全的序列化格式如 JSON 替代 pickle,特别是处理用户输入或网络传输数据时。如果必须使用 pickle,应结合 hmac 对数据进行签名验证以确保完整性,限制反序列化时可加载的类和白名单,并在隔离环境中运行。此外,避免在 API
📋 目录
  1. A Python Pickle 安全风险解析与 AI 模型防护实践
  2. B Python 中不安全的反序列化操作示例
  3. C pickle --- Python 对象序列化
  4. D FAQ
A A

在 Python 中安全地反序列化 pickle 文件的核心原则是绝对不要对不可信来源的数据进行 unpickle 操作。为了防止恶意代码执行,开发者应优先使用更安全的序列化格式如 JSON 替代 pickle,特别是处理用户输入或网络传输数据时。如果必须使用 pickle,应结合 hmac 对数据进行签名验证以确保完整性,限制反序列化时可加载的类和白名单,并在隔离环境中运行。此外,避免在 API 网关自动反序列化用户上传的模型文件,定期审计模型仓库文件完整性,是防止供应链攻击的关键措施。确保只加载信任的数据源,并考虑使用数字签名验证数据未被篡改,是防御此类漏洞的有效手段。

Python Pickle 安全风险解析与 AI 模型防护实践

"Pickle 风险"是 AI 系统部署中一个常被忽视却至关重要的安全隐患。作为数据序列化工具,Python 的 pickle 模块虽然方便,却隐藏着严重的安全漏洞。我在多个企业级 AI 项目中亲眼见证过,由于开发团队对 pickle 风险的认知不足,导致模型文件被恶意注入后门代码的案例。这个主题之所以被称为"AI 缺失学期"的内容,是因为它很少出现在正式课程中,却是实际工作中必须掌握的生存技能。本文将深入剖析 pickle 的工作原理、具体风险场景,并提供可立即落地的替代方案和安全实践。2. Pickle 工作机制解析 2.1 序列化原理剖析 Pickle 的核心功能是将 Python 对象转换为字节流 (序列化) 以及从字节流重建对象 (反序列化)。其工作流程看似简单:import pickle # 序列化 data = {"key": "value"} serialized = pickle.dumps(data) # 输出字节流 # 反序列化 loaded = pickle.loads(serialized) # 重建原始对象 一键获取完整项目代码 python 1 2 3 4 5 6 7 8 但危险正隐藏在看似无害的 loads() 操作中。与 JSON 等安全序列化格式不同,pickle 在反序列化时会自动执行__reduce__方法,这使得攻击者可以植入任意 Python 代码。2.2 攻击向量实证 通过一个简单的 PoC 可以直观理解风险:import pickle import os class Malicious: def __reduce__(self): return (os.system, ('rm -rf /',)) # 危险系统命令 payload = pickle.dumps(Malicious()) pickle.loads(payload) # 执行系统命令 一键获取完整项目代码 python 1 2 3 4 5 6 7 8 9 在企业环境中,攻击者可能将恶意代码隐藏在:共享的预训练模型文件 (.pkl) 分布式计算的任务序列化数据 模型注册表存储的权重文件 3. 企业级风险场景 3.1 供应链攻击案例 2022 年某金融科技公司的安全事件中,攻击者篡改了内部模型仓库中的 RandomForest 分类器 pkl 文件。当该模型被加载到风控系统时,攻击代码:窃取了内存中的信用卡数据 通过 DNS 隐蔽通道外传 保持了原始模型的预测准确性以规避检测 3.2 模型部署拓扑风险 现代 AI 系统的典型部署架构放大了 pickle 风险:[开发者笔记本] --pkl--> [模型仓库] --pkl--> [推理服务] | v [数据分析平台] 一键获取完整项目代码 1 2 3 每个传输节点都可能成为攻击入口点。更危险的是,有些企业会在 API 网关自动反序列化用户上传的模型文件。4. 安全替代方案 4.1 结构化数据序列化 对于简单数据结构,优先选择:(撰于 2026 年 4 月 26 日)

Python 中不安全的反序列化操作示例

1.Python 的 pickling 和 unpickling? pickling 和 unpickling 是指序列化和反序列化对象的过程。具体来说,pickling 是将一个 Python 对象转换为一个字节流,以便可以将其存储到文件中或通过网络传输;而 unpickling 是将字节流重新转换回原来的 Python 对象。1)Pickling 示例操作:为了实现 pickling,我们通常会使用 pickle 模块。例如:1 2 3 4 5 importpickle data ={"name": "Alice", "age": 25, "is_student": True} # 将对象序列化并写入文件 with open("data.pickle", "wb") as f: pickle.dump(data, f) 2)Unpickling 示例操作:对应地,要进行 unpickling,可以这样操作:1 2 3 4 5 importpickle # 从文件中读取字节流并反序列化为对象 with open("data.pickle", "rb") as f: data =pickle.load(f) print(data) # 输出:{'name': 'Alice', 'age': 25, 'is_student': True} 3) 安全性问题:值得注意的是,使用 pickle 时要小心安全问题。因为 pickle 可以执行任意代码,所以从不可信来源加载 pickle 数据是危险的,可能导致代码执行漏洞。因此,尽量避免加载未经验证的 pickle 文件。4) 絕對 file path 和相對文件存取:在实际应用中,我们可能会使用相对路径来读取或写入 pickle 文件,以增强代码的可移植性。例如:data.pickle 相较于绝对路径 "/path/to/data.pickle"更方便在不同环境下运行。5)pickle 模块的替代品:如果需要更安全的序列化方法,可以考虑使用 json 模块,它只支持基本数据类型的序列化和反序列化,并不执行任何代码。因此,它是更安全的选择,尽管功能上没有 pickle 强大。1 2 3 4 5 6 7 8 9 importjson data ={"name": "Alice", "age": 25, "is_student": True} # 序列化 with open("data.json", "w") as f: json.dump(data, f) # 反序列化 with open("data.json", "r") as f: data =json.load(f) print(data) # 输出:{'name': 'Alice', 'age': 25, 'is_student': True} 2. 如何利用 pickle 模块的反序列化来执行恶意代码?简单来说,pickle 之所以不安全,是因为它不仅仅是在存储数据,它还在存储**“如何构建对象”的指令**。1 1. 为什么 pickle 是不安全的?(资料日期为 2026 年 1 月 29 日)

pickle --- Python 对象序列化

模块 pickle 实现了对一个 Python 对象结构的二进制序列化和反序列化。"pickling"是将 Python 对象及其所拥有的层次结构转化为一个字节流的过程,而 "unpickling"是相反的操作,会将 (来自一个 binary file 或者 bytes-like object 的) 字节流转化回一个对象层次结构。pickling(和 unpickling) 也被称为“序列化”, “编组”1 或者“平面化”。而为了避免混乱,此处采用术语“封存 (pickling)"和“解封 (unpickling)"。pickle 模块并不安全。你只应该对你信任的数据进行 unpickle 操作。构建恶意的 pickle 数据来 在解封时执行任意代码是可能的。绝对不要对不信任来源的数据和可能被篡改过的数据进行解封。请考虑使用 hmac 来对数据进行签名,确保数据没有被篡改。在你处理不信任数据时,更安全的序列化格式如 json 可能更为适合。参见 与 json 模块的比较。与其他 Python 模块间的关系¶ 与 marshal 间的关系¶ Python 有一个更原始的序列化模块称为 marshal,但一般地 pickle 应该是序列化 Python 对象时的首选。marshal 存在主要是为了支持 Python 的 .pyc 文件.pickle 模块与 marshal 在如下几方面显著不同:pickle 模块会跟踪已被序列化的对象,所以该对象之后再次被引用时不会再次被序列化。marshal 不会这么做。这隐含了递归对象和共享对象。递归对象指包含对自己的引用的对象。这种对象并不会被 marshal 接受,并且实际上尝试 marshal 递归对象会让你的 Python 解释器崩溃。对象共享发生在对象层级中存在多处引用同一对象时。pickle 只会存储这些对象一次,并确保其他的引用指向同一个主副本。共享对象将保持共享,这可能对可变对象非常重要。marshal 不能被用于序列化用户定义类及其实例。pickle 能够透明地存储并保存类实例,然而此时类定义必须能够从与被存储时相同的模块被引入。同样用于序列化的 marshal 格式不保证数据能移植到不同的 Python 版本中。因为它的主要任务是支持 .pyc 文件,必要时会以破坏向后兼容的方式更改这种序列化格式,为此 Python 的实现者保留了更改格式的权利。pickle 序列化格式可以在不同版本的 Python 中实现向后兼容,前提是选择了合适的 pickle 协议。如果你的数据要在 Python 2 与 Python 3 之间跨越传递,封存和解封的代码在 2 和 3 之间也是不同的。(2026 年 1 月 12 日的资料)

如何在 Python 中安全地反序列化 pickle 文件防止恶意代码执行?

FAQ

pickle 反序列化漏洞的根本原因是什么?

根本原因在于 pickle 在反序列化时会自动执行__reduce__方法,这使得攻击者可以通过构造特定的序列化数据,使得反序列化过程触发恶意行为,如远程命令执行、数据泄露或系统崩溃。

有哪些安全的替代方案可以代替 pickle?

如何在 Python 中安全地反序列化 pickle 文件防止恶意代码执行?

如果需要更安全的序列化方法,可以考虑使用 json 模块,它只支持基本数据类型的序列化和反序列化,并不执行任何代码。因此,它是更安全的选择,尽管功能上没有 pickle 强大。

如何确保 pickle 数据未被篡改?

请考虑使用 hmac 来对数据进行签名,确保数据没有被篡改。绝对不要对不信任来源的数据和可能被篡改过的数据进行解封。