从不受信任的来源安全地序列化数据和解包

Joh*_*ohn 7 python yaml urllib2 pickle pyramid

我使用金字塔作为基于回合制视频游戏的数据传输的基础.客户端使用POST数据来显示他们的操作,并使用GET来检索序列化的游戏板数据.游戏数据有时可能涉及字符串,但几乎总是两个整数和两个元组:

gamedata = (userid, gamenumber, (sourcex, sourcey), (destx, desty))
Run Code Online (Sandbox Code Playgroud)

我的一般客户端框架是Pickle,转换为base 64,使用urlencode,并提交POST.然后,服务器接收POST,解压缩单项字典,解码base64,然后取消对数据对象的解开.

我想使用Pickle,因为我可以使用类和值.以POST字段提交游戏数据只能给我字符串.

然而,Pickle被认为是不安全的.所以,我转向pyYAML,它的用途相同.使用yaml.safe_load(data),我可以序列化数据而不会暴露安全漏洞.但是,safe_load是非常安全的,我甚至无法反序列化无害的元组或列表,即使它们只包含整数.

这里有一些中间地带吗?有没有办法序列化python结构,而不同时允许执行任意代码?

我的第一个想法是为我的发送和接收函数编写一个包装器,它使用值名称中的下划线来重新创建元组,例如send会将字典值转换source : (x, y)source_0 : x, source_1: y.我的第二个想法是,这不是一个非常明智的发展方式.

编辑:这是我使用JSON的实现...它看起来不像YAML或Pickle那么强大,但我仍然担心可能存在安全漏洞.

在我进行实验时,客户端的构建更加明显:

import urllib, json, base64

arbitrarydata = { 'id':14, 'gn':25, 'sourcecoord':(10,12), 'destcoord':(8,14)}

jsondata = json.dumps(arbitrarydata)
b64data = base64.urlsafe_b64encode(jsondata)
transmitstring = urllib.urlencode( [ ('data', b64data) ] )
urllib.urlopen('http://127.0.0.1:9000/post', transmitstring).read()
Run Code Online (Sandbox Code Playgroud)

Pyramid Server可以检索数据对象:

json.loads(base64.urlsafe_b64decode(request.POST['data'].encode('ascii')))
Run Code Online (Sandbox Code Playgroud)

在一个不相关的说明中,我很想听到关于在这种方法中使用POST数据的可接受性的其他意见,我的游戏客户端目前绝不是基于浏览器的.

Amb*_*ber 3

怎么样json?该库是标准 Python 库的一部分,它允许序列化大多数通用数据,而无需执行任意代码。