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

 更新时间:2026年01月29日 11:18:37   作者:保持持续学习  
本文给大家介绍了Python的pickling和unpickling过程,详细解释了如何利用pickle模块的反序列化来执行恶意代码,以及如何防范这种风险,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧

1.Python 的 pickling 和 unpickling?

pickling 和 unpickling 是指序列化和反序列化对象的过程。具体来说,pickling 是将一个 Python 对象转换为一个字节流,以便可以将其存储到文件中或通过网络传输;而 unpickling 是将字节流重新转换回原来的 Python 对象。

1)Pickling 示例操作: 为了实现 pickling,我们通常会使用 pickle 模块。例如:

import pickle
data = {"name": "Alice", "age": 25, "is_student": True}
# 将对象序列化并写入文件
with open("data.pickle", "wb") as f:
    pickle.dump(data, f)

2)Unpickling 示例操作: 对应地,要进行 unpickling,可以这样操作:

import pickle
# 从文件中读取字节流并反序列化为对象
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 强大。

import json
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. 为什么 pickle 是不安全的?

pickle 的设计目标是序列化几乎任何 Python 对象。为了实现这一点,它使用了一种名为 Stack Machine(栈机) 的机制。

当你“反序列化”(unpickling)一个文件时,你实际上是在运行一段 Pickle 虚拟机代码pickle 模块会盲目地执行这些指令来重建对象。如果指令说“去运行这个系统命令”,Python 就会照办。

核心风险点: pickle.load() 并没有任何沙箱保护。它信任它读取的所有数据。

2. 为什么可以执行任意代码?

这主要归功于 Python 对象协议中的一个特殊魔术方法:__reduce__

pickle 尝试序列化一个对象时,它会检查该对象是否有 __reduce__ 方法。如果有,该方法必须返回一个元组。这个元组最常见的情况包含两个元素:

  • 一个可调用对象(函数)
  • 一个参数元组,供上述函数调用。

在反序列化时,pickle 会自动调用这个函数并传入参数。这就是攻击点。

3. Python 例子演示

让我们通过代码来看看如何构建一个“恶意”的 pickle 包。

下面的代码创建了一个类,它的 __reduce__ 方法指示 pickle 在解封时运行系统命令(例如在 Windows 上打开计算器,或在 Linux/Mac 上创建一个文件)。

import pickle
import os
class MaliciousPickle:
    def __reduce__(self):
        # os.system 是我们要调用的函数
        # ('calc',) 是传给它的参数(Windows 下打开计算器)
        # 如果是 Linux/Mac,可以改为 ('touch /tmp/hacked.txt',)
        return (os.system, ('calc',))
# 1. 序列化:黑客生成恶意的 pickle 数据
evil_data = pickle.dumps(MaliciousPickle())
# 2. 假设我们将 evil_data 发送给了受害者
# 3. 反序列化:受害者仅仅是想“读取数据”
print("正在解封数据...")
pickle.loads(evil_data)  # 此时,计算器程序会被弹出!

在上面的例子中,pickle.loads() 本意是恢复一个对象,但它却执行了 os.system('calc')

  • 如果黑客把命令换成 rm -rf /(删除系统文件)。
  • 或者换成一个反弹 Shell(Reverse Shell),远程控制你的服务器。
  • 你的程序甚至不需要以管理员权限运行,只要它有权限执行的操作,黑客都能做。

4. 如何防范?

  • 永远不要 pickle.load() 来自不信任来源的数据。 这是金科玉律。
  • 使用更安全的格式: 优先选择 JSONXMLMessagePack。这些格式只存储纯数据,不包含执行逻辑。
  • 签名验证: 如果必须使用 pickle,请使用 hmac 对数据进行签名,确保数据在传输过程中没有被篡改。

pickle 是为了方便和灵活而设计的,但这种灵活性赋予了数据“生命”,让它在被加载时能执行动作。在安全领域,**“数据与指令混淆”**通常是漏洞的根源。

3.Json模块的反序列化为啥是安全的?

json 模块之所以被认为是安全的,核心原因在于它的本质属性解析机制pickle 完全不同。

我们可以从以下三个维度来拆解为什么 JSON 不会像 pickle 那样“反客为主”:

1. 数据 vs 指令 (Data vs. Code)

这是最根本的区别。

  • Pickle 是一种“脚本”: pickle 序列化的结果实际上是一串给 Pickle 虚拟机运行的指令。它包含“创建对象”、“查找模块”、“调用函数”等操作。正如我们之前看到的,__reduce__ 就像是在数据包里藏了一张“指令单”。
  • JSON 是“纯描述”: JSON(JavaScript Object Notation)是一种声明式的数据交换格式。它只能表示有限的几种数据类型:字符串、数字、布尔值、null、数组(列表)和对象(字典)。

打个比方:

  • Pickle 就像是你收到一个包裹,里面有一张纸条写着:“去厨房打开煤气灶”。如果你照做了,就会发生动作。
  • JSON 就像是你收到一张清单,上面写着:“苹果:5个,香蕉:3个”。这张纸条本身没有任何权力让你去做动作,它只是在描述状态。

2. 解析器的局限性

json.loads() 的工作原理是极其受限的。

当你运行 json.loads(data) 时,Python 的 JSON 解析器只会在内存中构建基础的内置类型(如 dict, list, str)。它完全不知道什么是 Python 类,也没有机制去触发 os.system() 这样的外部系统调用。

在解析 JSON 时,即便你在 JSON 字符串里写了类似代码的内容:

{
    "command": "os.system('rm -rf /')"
}

解析器也只会把它当作一个普通的字符串。除非你自己在代码里显式地拿到这个字符串并传给 eval() 执行,否则它就只是一串死板的字符。

3. 缺乏“对象重建”机制

pickle 之所以危险,是因为它支持自动重建自定义对象

  • pickle 中,如果数据说它是 MyClass 类型,pickle 会尝试导入这个类并实例化它。
  • json 中,没有任何语法可以指定“这是一个某个类的实例”。JSON 只知道 [] 是数组,{} 是键值对。

比较表

特性PickleJSON
本质二进制指令流(可执行)文本字符串(纯数据)
支持类型几乎所有 Python 对象仅基础类型 (str, int, dict, list等)
自定义类自动触发 __init____reduce__不支持,除非手动编写解析逻辑
安全性不安全 (信任数据即信任代码)安全 (解析过程不涉及逻辑执行)

4. 潜在的例外(安全警告)

虽然 json.loads() 本身是安全的,但作为开发者,如果处理不当仍会引入风险:

  • 后期处理漏洞: 如果你把解析出来的 JSON 数据直接传给了 eval()exec() 或者数据库查询语句(SQL 注入),那么危险依然存在。
  • 拒绝服务攻击 (DoS): 极度深层嵌套的 JSON(例如 [[[[...]]]])可能会消耗大量的 CPU 或内存资源,导致程序崩溃,但这属于稳定性问题,而非任意代码执行。

总结

JSON 的安全性源于它的简单性被动性。它只是一面反映数据的镜子,而 pickle 却是一台藏在盒子里的微型计算机。

既然我们谈到了安全的数据交换,你想了解一下如何为你的 JSON 数据添加“数字签名”,以确保它在传输过程中没有被第三方篡改吗?

参考文档

https://docs.python.org/zh-cn/3/library/pickle.html

https://www.runoob.com/python3/python-pickle.html

https://www.datacamp.com/tutorial/pickle-python-tutorial

到此这篇关于Python中不安全的反序列化操作示例的文章就介绍到这了,更多相关Python不安全反序列化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python 时间操作datetime详情(下)

    Python 时间操作datetime详情(下)

    我们在上一文datetime模块对datetime模块中包含了六个类对象如date、time、datetime等对时间和日期进行操作。这一篇文章我们继续上一篇文章的内容学习datetime模块中六大类的相关方法和属性
    2021-11-11
  • python3 求约数的实例

    python3 求约数的实例

    今天小编就为大家分享一篇python3 求约数的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-12-12
  • Python实现定时任务的九种方案总结

    Python实现定时任务的九种方案总结

    定时任务是编程中常见的需求,它可以按照预定的时间表执行特定的任务或操作,在Python中,有多种方法可以实现定时任务,下面小编就来和大家详细讲讲吧
    2023-11-11
  • 使用Python实现为PDF文件添加图章

    使用Python实现为PDF文件添加图章

    在日常工作中,我们经常需要给PDF文档添加一些标识,比如公司的图章或水印图章,所以本文就来为大家详细介绍一下如何使用Python实现为PDF文件添加图章,需要的可以参考下
    2023-11-11
  • Python语言技巧之三元运算符使用介绍

    Python语言技巧之三元运算符使用介绍

    现在大部分高级语言都支持“?”这个三元运算符(ternary operator),它对应的表达式如下:condition ? value if true : value if false。很奇怪的是,这么常用的运算符python居然不支持
    2013-03-03
  • Pandas操作两个Excel实现数据对应行的合并

    Pandas操作两个Excel实现数据对应行的合并

    本文主要介绍了Pandas操作两个Excel实现数据对应行的合并,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • pytorch自定义二值化网络层方式

    pytorch自定义二值化网络层方式

    今天小编就为大家分享一篇pytorch自定义二值化网络层方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-01-01
  • Python pypinyin注音库轻松丝滑实现汉字转换成拼音

    Python pypinyin注音库轻松丝滑实现汉字转换成拼音

    pypinyin 库,能像功夫熊猫那样,轻松、快捷地帮你把汉字转换成拼音,有了 pypinyin,不仅可以节省宝贵的时间,还可以更准确地展示中文字符的读音,使文化交流更为顺畅,本文带大家一起探索 pypinyin 库的魅力
    2024-01-01
  • python如何获取apk的packagename和activity

    python如何获取apk的packagename和activity

    这篇文章主要介绍了python如何获取apk的packagename和activity,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • pytorch 多个反向传播操作

    pytorch 多个反向传播操作

    这篇文章主要介绍了pytorch 多个反向传播操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-05-05

最新评论