flawopen.com/不安全的反序列化/Python pickle 安全
Python 的 pickle.load() 能安全加载不可信数据吗?
不能。应把 pickle 当作包裹中的程序,而不是被动数据记录:加载时可能在应用验证对象前触发重建行为。跨越信任边界的数据应使用纯数据格式。
import pickle # Never accept pickle bytes from a request, upload, # shared cache, or other untrusted source. obj = pickle.loads(untrusted_bytes)
import json
def parse_profile(raw: bytes) -> dict[str, str]:
if len(raw) > 65_536:
raise ValueError("Payload too large")
try:
value = json.loads(raw)
except (json.JSONDecodeError, UnicodeDecodeError):
raise ValueError("Invalid JSON") from None
if not isinstance(value, dict) or set(value) - {"display_name", "theme"}:
raise ValueError("Invalid profile")
name = value.get("display_name")
theme = value.get("theme")
if not isinstance(name, str) or len(name) > 80:
raise ValueError("Invalid display name")
if theme not in {"light", "dark"}:
raise ValueError("Invalid theme")
return {"display_name": name, "theme": theme}
- Pickle 流:
- Python 特有的字节序列,用于描述对象重建,包括全局对象引用和重建行为。
- Unpickling:
- 解释数据流并重建对象图;过程中可能调用函数。
- 信任边界:
- 用户、服务、上传内容或共享存储能够控制或修改字节的位置。
- CWE-502:
- 不可信数据反序列化;风险取决于攻击者能否提供或篡改应用加载的数据。
不可信字节进入 pickle 加载点
上传、请求、缓存或制品可能将攻击者控制或篡改的 pickle 数据带入进程。
Unpickler 解析全局对象
解释器处理重建指令;find_class() 可导入并返回命名的全局对象,包括函数。
加载过程触发行为
指令可在 load() 或 loads() 执行时调用函数,早于应用对结果的检查。
影响取决于进程权限
行为使用 Python 进程的权限。网络、秘密、文件访问和隔离决定影响范围。
为什么加载 pickle 会跨越代码执行边界
pickle 流可指定全局对象和重建函数。反序列化时,Unpickler.find_class() 解析全局对象(包括函数),操作码随后可触发重建。风险操作就是 pickle.load() 或 pickle.loads();无需后续单独调用 execute。执行行为继承进程权限。这是格式文档说明的行为;不要用 pickle 交换不可信数据。
JSON 能解决什么,不能解决什么
Python 文档警告,不可信或被篡改的 pickle 数据可能执行任意代码;JSON 解码本身不会产生这条任意代码执行路径。JSON 不会自动验证输入:限制大小,要求预期顶层类型和字段,按结构验证值,并单独执行授权检查。若旧系统暂时必须加载 pickle,应先用受保护密钥验证确切字节;签名仅在密钥假设成立时证明来源和完整性,不能让可信签署者提供的恶意数据变安全。应迁移到纯数据格式。
- ✓从处理请求、上传、共享缓存或来源不明制品的路径中移除
pickle.load()和pickle.loads()。 - ✓使用 JSON 等纯数据格式,并限制大小、验证结构与允许字段、限制值范围及执行 endpoint 授权。
- ✓可信内部流程暂时保留 pickle 时,先验证确切字节的 HMAC 或签名,保护密钥并降低进程权限。
- ✓在代码与数据流中查找 pickle 使用点,确认谁能写入或篡改来源,并迁移或隔离风险点。
常见问题
重写 find_class() 限制全局对象可以降低风险,但很难证明加载器对所有协议和可达行为都安全。不要把允许列表作为用户字节的默认防护;优先使用纯数据格式。
需要。JSON 解码不会触发 pickle 式任意代码执行,但应用仍要检查类型、字段、大小、值和授权。应将 JSON 解析与业务规则分开。