我有一个网站,用户可以在其中输入数学方程式(表达式),然后根据网站提供的数据(常数)评估这些方程式。所需的数学运算包括符号、算术运算、min()
、max()
和其他一些基本函数。一个示例方程可以是:
max(a * b + 100, a / b - 200)
可以使用 Python 简单地 eval()
,但众所周知,这会导致网站受损。进行数学方程评估的安全方法是什么?
如果选择使用 Python 本身来评估表达式,是否有任何 Python 沙箱会限制 Python,因此只有用户供应商运算符和函数可用。成熟的 Python,就像定义函数一样,应该完全禁用。子流程没问题(见 PyPy sandbox)。特别是,应该关闭用于利用内存和 CPU 使用的 for 循环和其他漏洞。
最佳答案
免责声明:我是另一个答案的代码中提到的 Alexer。老实说,我只是半开玩笑地建议了字节码解析方法,因为我碰巧有 99% 的代码用于一个不相关的项目,因此可以在几分钟内完成 POC。也就是说,它本身不应该有任何问题。只是它是这项任务所需的更复杂的机器。事实上,您应该只需反汇编代码 [根据白名单检查操作码],检查常量和名称是否有效,然后使用普通的邪恶 eval 执行它,就可以逃脱惩罚.您应该失去在整个执行过程中插入偏执的额外检查的能力。 (另一个免责声明:我仍然不会觉得用 eval 来做这件事)
无论如何,我有一个无聊的时刻,所以我写了一些代码以聪明的方式做到这一点;使用 AST 而不是字节码。它只是 compile()
的一个额外标志。 (或者只是 ast.parse()
,因为无论如何你都需要模块中的类型)
import ast
import operator
_operations = {
ast.Add: operator.add,
ast.Sub: operator.sub,
ast.Mult: operator.mul,
ast.Div: operator.div,
ast.Pow: operator.pow,
}
def _safe_eval(node, variables, functions):
if isinstance(node, ast.Num):
return node.n
elif isinstance(node, ast.Name):
return variables[node.id] # KeyError -> Unsafe variable
elif isinstance(node, ast.BinOp):
op = _operations[node.op.__class__] # KeyError -> Unsafe operation
left = _safe_eval(node.left, variables, functions)
right = _safe_eval(node.right, variables, functions)
if isinstance(node.op, ast.Pow):
assert right < 100
return op(left, right)
elif isinstance(node, ast.Call):
assert not node.keywords and not node.starargs and not node.kwargs
assert isinstance(node.func, ast.Name), 'Unsafe function derivation'
func = functions[node.func.id] # KeyError -> Unsafe function
args = [_safe_eval(arg, variables, functions) for arg in node.args]
return func(*args)
assert False, 'Unsafe operation'
def safe_eval(expr, variables={}, functions={}):
node = ast.parse(expr, '<string>', 'eval').body
return _safe_eval(node, variables, functions)
if __name__ == '__main__':
import math
print safe_eval('sin(a*pi/b)', dict(a=1, b=2, pi=math.pi), dict(sin=math.sin))
这与字节码版本相同;如果您根据白名单检查操作并检查名称和值是否有效,您应该能够在 AST 上调用 eval 。 (但同样,我仍然不会这样做。因为偏执狂。当涉及到 eval 时,偏执狂是好的)
关于python - 从 Python 中的不安全用户输入评估数学方程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26505420/