我正在编写一个网络应用程序,它将用户输入存储在一个对象中。该对象将被腌制。
用户是否有可能制作恶意输入,在对象未腌制时做出一些令人震惊的事情?
这是一个非常基本的代码示例,它忽略了封装等精彩原理,但概括了我正在查看的内容:
import pickle
class X(object):
some_attribute = None
x = X()
x.some_attribute = 'insert some user input that could possibly be bad'
p = pickle.dumps(x)
# Can bad things happen here if the object, before being picked, contained
# potentially bad data in some_attribute?
x = pickle.loads(p)
是与否...
不 - 除非解释器或 pickle 模块存在错误,否则您不能通过 pickled 文本或类似的东西运行任意代码。除非稍后对腌制文本进行
eval
编辑,或者您正在执行诸如使用此数据中提到的类型创建新对象之类的操作。
是的 - 根据您稍后计划如何处理对象中的信息,用户可以执行各种操作。从 SQL 注入尝试,到更改凭据、暴力破解密码或验证用户输入时应考虑的任何内容。但您可能正在检查所有这些。
编辑:
Python 文档指出了这一点:
警告 pickle 模块并非旨在防止错误或恶意构造的数据。切勿取消从不受信任或未经身份验证的来源收到的数据。
但这不是您的情况 - 您接受输入,将其通过常规验证,然后对其进行腌制。
我在多处理模块的文档中找到了这个,我认为它回答了问题:
警告
Connection.recv() 方法会自动取消它的数据 接收,这可能会带来安全风险,除非您可以信任 发送消息的进程。
因此,除非连接对象是使用 Pipe() 生成的 应该只在执行一些操作后使用recv()和send()方法 某种身份验证。请参阅身份验证密钥。
(强调我的)
结论是,如果连接对象是使用可信管道(即可信pickle)生成的,那么可以安全地取消pickle。
正如@Not_A_Golfer所说,这有点模棱两可。
在 2024 年,如果你正在考虑这个,IMO 最好的方法是使用 pydantic 并使用 json 序列化