python中的评估安全性,从JSON中提取的字符串



我绞尽脑汁试图找到一种利用此设置的方法。我的概念是这样的:我的扭曲服务器接收消息(通过LineReceiver)。消息是 base64 JSON,它应该包含一个字典。字典有一个"INSTRUCTION"键,指示服务器应处理哪种客户端操作。

在程序的这一部分,line是通过网络接收的base64字符串。

def Decode(line):
return json.loads(base64.b64decode(line))

和解释(在一个扭曲的Protocol物体内)

def lineReceived(self, line):
instruction = Decode(line)  #dict
if instruction and "INSTRUCTION" in instruction:
if instruction["INSTRUCTION"] in ("register", "join", "create", 
"list", "passturn", "impmove", "warpmove","laserattack",
"torpattack", "mine", "data", "status"):
cmdstring = instruction["INSTRUCTION"] + "(self)"
eval(cmdstring)

为什么我认为它是安全的:

  • eval 只有在我得到一个纯字符串作为值时才会运行。
  • JSON不能打包复杂的对象,只能打包python基础知识。攻击者不应该__str__我收到的内容的访问权限,对吧?
  • 我正在使用 eval 为十几行提供可读性较差但更紧凑的替代品if instruction["INSTRUCTION"] == "functionA": functionA(self)。我只是运行 eval 以从特定列表中选择一个函数。

这安全吗?这被认为是可接受的风格或形式吗?由于客户端不可信,此代码块对于多人游戏是否足够健壮?(稍后会验证指令是否遵循游戏规则,在这里我想保护我的服务器免受破坏性修补。

有没有更好的方法来做我正在尝试的事情(我想是远程执行函数),更标准/更安全?

你最好使用getattr()

if instruction and "INSTRUCTION" in instruction:
instr_callable = getattr(self, 'do_' + instruction['INSTRUCTION'], None)
if instr_callable is not None:
instr_callable()

其中do_以指令名称为前缀,以确保仅通过此方法调用允许的方法。

如果您的指令函数位于全局命名空间中,请改用globals(),并将其用作映射:

if instruction and "INSTRUCTION" in instruction:
instr_callable = globals().get('do_' + instruction['INSTRUCTION'], None)
if instr_callable is not None:
instr_callable(self)

但是,最好将这些可调用对象放在显式映射中:

instr_callables = dict(
register=register,
join=join,
...
)
if instruction and "INSTRUCTION" in instruction:
instr_callable = instr_callables.get(instruction['INSTRUCTION'], None)
if instr_callable is not None:
instr_callable(self)

eval()很少(如果有的话)需要在 python 命名空间中查找任意对象。

最新更新