在不使用导入机器的情况下访问模块 'sys'

Access module 'sys' without using import machinery

沙盒 Python 由于语言中内置的反射功能的强大功能,代码是出了名的困难。最起码要把import机制和大部分内建函数和全局变量拿掉,即使这样也有漏洞(比如{}.__class__.__base__.__subclasses__())。

在 Python 2 和 3 中,'sys' 模块内置于解释器中,并在用户代码开始执行之前预加载(即使在 -S 模式下)。如果您可以获得 sys 模块的句柄,那么您就可以访问已加载模块的全局列表 (sys.modules),这使您可以做各种顽皮的事情。

所以,问题是:从一个空模块开始,根本不使用导入机制(没有import声明,没有__import__,没有imp 库等),并且不使用通常在 __builtins__ 中找到的任何内容,除非您可以通过其他方式获得它的句柄,是否可以获取对 syssys.modules? (每个指向另一个。)我对 2.x 和 3.x 答案都感兴趣。

__builtins__ 通常可以恢复,为您提供返回 __import__ 的路径,从而返回任何模块。

对于Python3 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)>

在Python2中,你只需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 版本只需要解包您在 类 上找到的未绑定方法即可获得相同的结果:

>>> 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)>