Python对象序列化用Pickle安全吗

wen python案例 16

本文目录导读:

Python对象序列化用Pickle安全吗

  1. 为什么危险?
  2. 安全使用场景
  3. 不安全场景
  4. 更好的替代方案
  5. 如果必须用 Pickle 且不信任来源

不安全,绝不应用于不受信任的数据或反序列化场景。

Pickle 存在的核心安全问题在于:它不是一个只存数据的格式,而是一个基于栈的虚拟机协议,反序列化时,Pickle 会重新执行构建对象的字节码指令,这意味着攻击者可以构造恶意的 Pickle 数据,在反序列化过程中执行任意 Python 代码。

为什么危险?

Pickle 序列化的不是数据,而是“如何重建对象”的指令,一个经典的攻击载荷如下:

import pickle
import os
# 攻击者构造的恶意 pickle 数据
class Evil:
    def __reduce__(self):
        return (os.system, ('echo 你被入侵了',))
pickle_data = pickle.dumps(Evil())
# 反序列化时,会执行 os.system('echo 你被入侵了')
pickle.loads(pickle_data)  # 危险!

只要 pickle.loads 被调用,这段代码就会执行,攻击者可以换成 rm -rf / 或其他破坏性命令。

安全使用场景

  • 可信环境内部:如进程间通信、临时缓存(且双方代码可控)
  • 短期存储:自己生成的 pickle,只由自己读取
  • 签名验证:先对 pickle 数据做 HMAC 签名,反序列化前校验完整性

不安全场景

  • 客户端上传的数据:如 Web 应用的 session 存储
  • 来自网络的未验证数据:如 API 接收的二进制流
  • 用户输入的文件:如让用户上传 .pkl 文件加载

更好的替代方案

需求 推荐方案 原因
安全数据交换 JSON (+ schema验证) 纯数据,不执行代码
复杂Python对象 MessagePackcloudpickle (仅可信环境) 相比pickle更可控
高性能 Protocol BuffersApache Arrow 跨语言,类型安全
配置文件 YAML (用 safe_load) 避免任意代码执行

如果必须用 Pickle 且不信任来源

import pickle
import hmac
import hashlib
# 写入时签名
secret_key = b'your-secret-key'
data = pickle.dumps(obj)
signature = hmac.new(secret_key, data, hashlib.sha256).digest()
# 存储 signature + data
# 读取时验证签名
stored_sig = data[:32]  
stored_data = data[32:]
expected_sig = hmac.new(secret_key, stored_data, hashlib.sha256).digest()
if hmac.compare_digest(stored_sig, expected_sig):
    obj = pickle.loads(stored_data)
维度
是否安全 🚫 不安全
能否用于用户输入 绝对不能
内部使用 可以,但要谨慎
最佳实践 尽量用 JSON/jsonlines/Avro/Parquet

记住这条黄金法则:永远不要对不可信的数据调用 pickle.loads()

抱歉,评论功能暂时关闭!