由于语言中内置的反射功能的强大功能,对 Python 代码进行沙盒处理是出了名的困难。最起码要去掉import
机制和大部分内置函数和全局变量,即使这样也有漏洞({}.__class__.__base__.__subclasses__()
,例如)。
在 Python 2 和 3 中,“sys”模块内置于解释器中,并在用户代码开始执行之前预加载(即使在 -S
模式下)。如果您可以获得 sys
模块的句柄,那么您就可以访问已加载模块的全局列表 (sys.modules
),这使您可以做各种顽皮的事东西。
所以,问题是:从一个空模块开始,根本不(没有import
语句,没有__import__
,没有 imp
库等),也没有使用通常在 __builtins__
中找到的任何东西,除非你可以通过其他方式获得它的句柄,是否有可能获得对sys
还是 sys.modules
? (每个指向另一个。)我对 2.x 和 3.x 的答案都感兴趣。
最佳答案
__builtins__
通常可以恢复,为您提供返回 __import__
的路径,从而返回任何模块。
对于 Python 3 this comment from eryksun有效,例如:
>>> f = [t for t in ().__class__.__base__.__subclasses__()
... if t.__name__ == 'Sized'][0].__len__
>>> f.__globals__['__builtins__']['__import__']('sys')
<module 'sys' (built-in)>
在 Python 2 中,你只需 look for a different object :
>>> f = [t for t in ().__class__.__base__.__subclasses__()
... if t.__name__ == 'catch_warnings'][0].__exit__.__func__
>>> f.__globals__['__builtins__']['__import__']('sys')
<module 'sys' (built-in)>
这两种方法都查找可以使用文字语法(此处为元组)创建的内置类型的子类,然后在该子类上引用函数对象。函数对象有一个 __globals__
字典引用,它会给你返回 __builtins__
对象。
请注意,您不能只说no __import__
,因为它是__builtins__
无论如何的一部分。
但是,许多 __globals__
对象都必然有 sys
已经存在。例如,在 Python 3 上搜索 sys
模块时,我可以立即访问一个模块:
>>> next(getattr(c, f).__globals__['sys']
... for c in ().__class__.__base__.__subclasses__()
... for f in dir(c)
... if isinstance(getattr(c, f, None), type(lambda: None)) and
... 'sys' in getattr(c, f).__globals__)
<module 'sys' (built-in)>
Python 2 版本只需要解包您在类上找到的未绑定(bind)方法即可获得相同的结果:
>>> next(getattr(c, f).__func__.__globals__['sys']
... for c in ().__class__.__base__.__subclasses__()
... for f in dir(c)
... if isinstance(getattr(c, f, None), type((lambda: 0).__get__(0))) and
... 'sys' in getattr(c, f).__func__.__globals__)
<module 'sys' (built-in)>
关于python - 不使用进口机器访问模块 'sys',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33880646/