禁用 pickle.loads 处理不可信数据,改用 json.loads;若必须用 pickle,则需签名验证与沙箱隔离,并排查第三方库隐式调用。

别用 pickle.loads 处理任何来自用户、网络或不可信来源的数据——这是最直接有效的修复起点。
为什么 pickle 在 Flask 里特别危险
Flask 本身不禁止反序列化,但 pickle 的设计决定了它必须执行任意 Python 代码才能还原对象。只要攻击者能控制输入(比如 POST body、URL 参数、上传文件内容),就能构造恶意 payload 触发命令执行。
常见触发点包括:request.data、request.get_data()、request.files['xxx'].read() 等直接喂给 pickle.loads() 的场景。
- 错误示例:
pickle.loads(request.data)、pickle.load(io.BytesIO(request.get_data())) - 即使加了 try/except 也拦不住——异常前代码已执行
- Python 3.14+ 的
pickle默认仍无安全模式,不能靠版本升级解决
用 json 替代 pickle 的实操要点
绝大多数业务场景根本不需要 pickle 的对象还原能力,用 json 完全够用,且天然免疫反序列化 RCE。
- 把
pickle.loads(data)改成json.loads(data.decode("utf-8"))(注意编码) - 发送端同步改用
json.dumps(obj).encode("utf-8") -
json不支持函数、类实例、datetime 等类型——这反而是好事,逼你显式转换 - 若需传 datetime,统一转为 ISO 格式字符串:
dt.isoformat();接收时用datetime.fromisoformat()
真没法换?那就加签名验证 + 沙箱隔离
仅当必须处理可信内部系统发来的 pickle 数据(如微服务间通信),才考虑加固方案,且必须满足两个前提:数据源绝对可控、传输链路已加密(HTTPS 或内网直连)。
- 签名验证:用
hmac对原始字节做摘要,和数据一起传输,服务端先验签再反序列化 - 沙箱隔离:把
pickle.loads()放进独立子进程,超时强制 kill,限制资源(CPU、内存、网络) - 禁用危险模块:通过自定义
find_class钩子,白名单只允许基础类型(dict、list、str等) - 别信
restricted_python类库——它们维护滞后,绕过方法已公开,生产环境慎用
真正容易被忽略的是:很多团队以为“没用 pickle.loads 就安全”,却忘了第三方库(如某些旧版 celery、redis-py 默认序列化器)或内部封装工具可能偷偷调用它。建议全局 grep import pickle 和 pickle\.,逐个确认调用上下文。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











