Python 序列化与反序列化

Python 序列化与反序列化:pickle 模块

什么是序列化和反序列化?

  • 序列化:就是将一个对象的状态信息转换为可以存储或传输的格式的过程。换句话说,就是将一个复杂的对象拆分成一系列的字节,以便存储在文件、内存、数据库中,或者通过网络传输给其他计算机。
  • 反序列化:在 Python 中,反序列化是将之前序列化(pickle)过的字节流还原成原始 Python 对象的过程。这就像把一个打包好的盒子拆开,恢复里面的物品一样。

为什么需要序列化?

  • 数据持久化:将 Python 对象保存到磁盘,以便在程序下次运行时恢复。
  • 网络传输:将对象通过网络传输给其他程序。
  • 进程间通信:在多个进程之间传递对象。

Python 的 pickle 模块

Python 的 pickle 模块提供了强大的序列化和反序列化功能。它可以将几乎所有的 Python 对象(包括自定义类)转化为字节流,然后再将其还原回来。

基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import pickle

# 创建一个对象
class Person:
def __init__(self, name, age):
self.name = name
self.age = age

person = Person("Alice", 30)

# 序列化
with open('person.pkl', 'wb') as f:
pickle.dump(person, f)

# 反序列化
with open('person.pkl', 'rb') as f:
person_reloaded = pickle.load(f)

print(person_reloaded.name, person_reloaded.age) # 输出:Alice 30

核心函数

  • pickle.dumps(obj):将对象序列化为字节字符串。
  • pickle.dump(obj, file):将对象序列化到文件中。
  • pickle.loads(bytes):将字节字符串反序列化为对象。
  • pickle.load(file):从文件中读取并反序列化对象。

pickle 的优点

  • 简单易用:API 简单,使用方便。
  • 高效:序列化和反序列化的速度较快。
  • 支持自定义类:可以序列化自定义类。

pickle 的缺点

  • 安全性:pickle 序列化的数据是不安全的,如果从不受信任的来源加载 pickle 数据,可能会执行恶意代码。
  • 平台依赖性:不同 Python 版本或不同平台生成的 pickle 文件可能不兼容。

安全性注意事项

  • 不要从不受信任的来源加载 pickle 数据。
  • 使用 loads() 函数时,谨慎处理
  • 考虑使用更安全的序列化格式,如 JSON,但 JSON 无法序列化所有 Python 对象。

其他序列化方式

  • JSON:适用于序列化简单的 Python 对象,具有良好的可读性和跨平台性。
  • XML:用于存储和传输数据,具有自描述性。
  • MessagePack:比 JSON 更高效,但可读性稍差。
  • Protobuf:Google 开发的协议缓冲区,高效、灵活,适用于大规模数据传输。

总结

pickle 是 Python 中常用的序列化模块,但需要注意其安全性问题。在选择序列化方式时,应根据具体应用场景,综合考虑性能、安全性、可读性等因素。

何时使用 pickle?

  • 存储临时数据
  • 在同一应用程序的不同模块之间传递数据
  • 存储简单的数据结构

何时不使用 pickle?

  • 存储敏感数据
  • 从不受信任的来源加载数据
  • 需要跨语言、跨平台的序列化

建议

  • **谨慎使用 pickle.loads()**,最好对输入数据进行验证。
  • 对于敏感数据,考虑使用更安全的序列化方式,如 JSON 或 Protobuf。
  • 如果需要跨平台兼容性,注意 pickle 版本的差异

Python 反序列化:深入浅出

为什么需要反序列化?

  • 数据恢复:将存储在磁盘或数据库中的序列化数据恢复为可用的 Python 对象。
  • 网络通信:将从网络接收到的序列化数据还原为原始对象。
  • 进程间通信:在多个进程之间传递对象。

使用 pickle 模块进行反序列化

1
2
3
4
5
6
7
8
import pickle

# 从文件中读取序列化数据
with open('person.pkl', 'rb') as f:
person_reloaded = pickle.load(f)

# 使用反序列化后的对象
print(person_reloaded.name, person_reloaded.age)

反序列化的风险

  • 安全风险:
    • 任意代码执行:恶意构造的 pickle 数据可能包含可执行的 Python 代码,导致远程代码执行攻击。
    • 拒绝服务攻击:恶意构造的数据可能导致程序崩溃或资源耗尽。
  • 数据损坏:如果序列化数据被损坏或格式不正确,反序列化会失败。

安全注意事项

  • 不要从不受信任的来源加载 pickle 数据。
  • 使用 loads() 函数时,谨慎处理
  • 考虑使用更安全的序列化格式,如 JSON,但 JSON 无法序列化所有 Python 对象。

缓解反序列化漏洞的方法

  • 输入验证:对输入的数据进行严格的验证,确保其符合预期格式。
  • 类型检查:对反序列化后的对象进行类型检查,防止执行意外的操作。
  • 白名单机制:只允许反序列化特定的类或对象。
  • 沙箱环境:在沙箱环境中进行反序列化,限制可执行的操作。
  • 使用更安全的序列化格式:如 JSON、Protobuf 等。

总结

何时使用 pickle 反序列化?

  • 信任的数据源:当您完全信任序列化数据来源时,可以使用 pickle。
  • 内部数据传输:在同一应用程序的不同模块之间传递数据时,可以使用 pickle。

何时不使用 pickle 反序列化?

  • 不受信任的数据源:如果数据来自不受信任的来源,请谨慎使用 pickle。
  • 需要高安全性:对于需要高安全性的场景,建议使用更安全的序列化格式。

建议

  • **谨慎使用 pickle.loads()**,最好对输入数据进行验证。
  • 对于敏感数据,考虑使用更安全的序列化方式,如 JSON 或 Protobuf。
  • 如果需要跨平台兼容性,注意 pickle 版本的差异

Python 反序列化攻击示例:一个简单的场景

漏洞成因

Python 的 pickle 模块虽然提供了方便的序列化和反序列化功能,但如果未经严格验证就对来自不受信任来源的序列化数据进行反序列化,就可能导致严重的漏洞。攻击者可以构造恶意的序列化数据,在反序列化时执行任意代码,从而控制整个系统。

攻击示例

假设我们有一个简单的 Web 应用程序,它接收用户提交的序列化数据,并将其反序列化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import pickle

def handle_request(data):
try:
obj = pickle.loads(data)
# ... 对对象进行操作
print(obj.execute()) # 危险!直接执行对象的方法
except Exception as e:
print(f"Error: {e}")

# 从请求中获取序列化数据
serialized_data = request.POST['data']

# 反序列化并执行
handle_request(serialized_data)

攻击者可以构造如下恶意序列化数据:

Python

1
2
3
4
5
6
7
8
import pickle

class EvilObject:
def __reduce__(self):
return (os.system, ('ls -la',)) # 执行系统命令

evil_obj = EvilObject()
serialized_data = pickle.dumps(evil_obj)

攻击流程:

  1. 攻击者将构造好的恶意序列化数据发送给服务器。
  2. 服务器接收到数据后,调用 pickle.loads() 进行反序列化。
  3. 在反序列化过程中,Python 会调用 EvilObject 类的 __reduce__ 方法,从而执行 os.system('ls -la') 命令,列出服务器上的文件。

攻击影响:

  • 任意代码执行:攻击者可以构造任意 Python 代码,并通过反序列化执行。
  • 数据泄露:攻击者可以读取服务器上的敏感文件。
  • 拒绝服务攻击:攻击者可以构造耗尽资源的代码,导致服务器崩溃。

如何防御?

  • 输入验证:对输入的序列化数据进行严格的验证,确保其符合预期格式。
  • 类型检查:对反序列化后的对象进行类型检查,防止执行意外的操作。
  • 白名单机制:只允许反序列化特定的类或对象。
  • 沙箱环境:在沙箱环境中进行反序列化,限制可执行的操作。
  • 使用更安全的序列化格式:如 JSON、Protobuf 等。

总结

Python 反序列化漏洞是由于对输入数据缺乏足够的验证和过滤导致的。攻击者可以利用这个漏洞执行任意代码,造成严重的安全后果。因此,在使用 pickle 进行序列化和反序列化时,务必注意安全问题,采取相应的防护措施。

参考资源:


Python 序列化与反序列化
https://chrrr1y.github.io/2024/08/15/Python序列化/
作者
Chrrr1y
发布于
2024年8月15日
更新于
2024年8月15日
许可协议