这是一个有点奇怪的 Python 问题。
考虑以下 Python 代码:
def controlled_exec(code):
x = 0
def increment_x():
nonlocal x
x += 1
globals = {"__builtins__": {}} # remove every global (including all python builtins)
locals = {"increment_x": increment_x} # expose only the increment function
exec(code, globals, locals)
return x
Run Code Online (Sandbox Code Playgroud)
我希望这个函数能够提供一个受控代码 API,它可以简单地计算调用次数increment_x()。我尝试了一下,得到了正确的行为。
# returns 2
controlled_exec("""\
increment_x()
increment_x()
""")
Run Code Online (Sandbox Code Playgroud)
我认为这种做法并不安全,但出于好奇我想知道。我可以x通过执行代码来设置任意值(比如负数)吗controlled_exec(...)?我该怎么做呢?
是的,x可以通过 执行的代码设置为任意值controlled_exec。
考虑以下演示:
def controlled_exec(code):
x = 0
def increment_x():
nonlocal x
x += 1
print(f"{x=}")
globals = {"__builtins__": {}} # remove every global (including all python builtins)
locals = {"increment_x": increment_x} # expose only the increment function
exec(code, globals, locals)
return x
controlled_exec("""\
increment_x()
increment_x.__closure__[0].cell_contents = -100
increment_x()
""")
Run Code Online (Sandbox Code Playgroud)
这输出
x=1
x=-99
Run Code Online (Sandbox Code Playgroud)
这实在是没办法“保全” exec。无论您做什么,最终您都会执行任意 Python 代码,这些代码与您编写的代码一样可以自由访问和修改 Python 解释器的状态。
为了强调有意义的安全有多困难exec,请注意,尽管您尝试从执行的代码中隐藏内置函数,但攻击者仍然可以通过以下方式访问任何内置函数:
increment_x.__globals__['__builtins__']
Run Code Online (Sandbox Code Playgroud)
这只是试图利用此功能的人可以使用的数十种技巧之一。
我们可以修改变量这一事实x确实是一个温和的例子。实际上没有什么可以阻止传递的代码controlled_exec执行更多灾难性的操作,例如擦除硬盘驱动器或下载恶意软件。
| 归档时间: |
|
| 查看次数: |
70 次 |
| 最近记录: |