我有两个关于 Pysandbox 的问题:
如何实现的功能
eval
?我理解sandbox.execute()
相当于exec
,但我找不到任何东西,如果输入的代码是2 + 2
,那么它将返回4
,或者类似的东西。默认情况下,
sandbox.execute()
将传入的环境设为只读——即如果我这样做sandbox.execute('data.append(4)', locals={'data': [1, 2, 3]})
,则会发生错误。如何使传入的环境可读写?
我有两个关于 Pysandbox 的问题:
如何实现的功能eval
?我理解sandbox.execute()
相当于exec
,但我找不到任何东西,如果输入的代码是2 + 2
,那么它将返回4
,或者类似的东西。
默认情况下,sandbox.execute()
将传入的环境设为只读——即如果我这样做sandbox.execute('data.append(4)', locals={'data': [1, 2, 3]})
,则会发生错误。如何使传入的环境可读写?
啊哈,我看到上一个 PySandbox 版本 (1.5) 的行为与您描述的一样。我正在尝试 git master 分支。
对于问题 1,我认为 PySandbox 1.5 没有任何直接的选项。该代码是专门编写的,以尝试禁止在沙箱内修改或传输任何状态。sandbox.call(eval, CODE)
不是一个好的选择,因为你不能很容易地传入本地和全局命名空间(你可以尝试,但沙箱会代理它们,然后 eval() 将失败,因为本地和全局必须是真正的字典)。而且我相信您希望能够在这里设置本地和全局。
出于类似的原因,问题 2 也不简单。在当前的 git master 分支上,这两种方法都是可能的,但不清楚是因为错误还是设计:)
所以这里有两个问题的解决方案,它扩展了沙盒功能并使用了可能意味着私有接口的东西,但仍应与沙盒一样安全:
from sandbox.proxy import proxy
from sandbox.sandbox_class import _call_exec
def proxyNamespace(d):
return dict((str(k), proxy(v)) for k, v in d.iteritems())
def wrapeval(codestr, globs, locs):
subglobs = proxyNamespace(globs)
sublocs = proxyNamespace(locs)
return eval(codestr, subglobs, sublocs)
def eval_in_sandbox(sandbox, codestr, globs=None, locs=None):
if globs is None:
globs = {}
if locs is None:
locs = globs
return sandbox._call(wrapeval, (codestr, locs, globs), {})
def exec_in_sandbox_with_mutable_namespace(sandbox, codestr, globs=None, locs=None):
if globs is None:
globs = {}
if locs is None:
locs = globs
subglobs = proxyNamespace(globs)
sublocs = proxyNamespace(locs)
sandbox._call(_call_exec, (codestr, subglobs, sublocs), {})
globs.update(subglobs)
locs.update(sublocs)
现在,说了这么多,我强烈建议不要将任何实际生产代码或系统的安全性建立在这个 PySandbox 模块上。在查看代码时,它似乎完全充满了缺陷和漏洞。我认为攻击者不会花费超过一个小时左右的时间来找到通过这种安全性的方法。我也不认为这经过安全专业人士的任何认真审查,甚至整个社区的很大一部分。如果你想运行不受信任的代码并且让它根本无法影响你的进程,你需要更强大的东西,可能基于 AppArmor 或类似的东西。如果您只担心意外行为不当的代码,而不是恶意代码,这可能没问题,但实际上我什至不确定。
问题一:
sandbox.call(eval, "2+2")
问题2:
from sandbox import Sandbox, SandboxConfig
cfg=SandboxConfig('stdout')
import sys
out1 = sys.stdout
err1 = sys.stderr
with open("logfile.txt", "w") as f:
sys.stdout = sys.stderr = f
sandbox = Sandbox(cfg)
indata={'data': [1, 2, 3]}
sandbox.execute('a=list(data);a.append(4); print(str(a))', locals=indata)
sys.stdout = out1
sys.stderr = err1
with open("logfile.txt", "r") as f:
indata=eval(f.read())
print indata
关于问题 2 的一些评论,很难获得一个 Readable-Writebale 对象并同时从外部看到它。我想看看一些更聪明的方法。
输出:
$ python test.py
[1, 2, 3, 4]