在不使用导入机器的情况下访问模块 '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__
中找到的任何内容,除非您可以通过其他方式获得它的句柄,是否可以获取对 sys
或sys.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)>
沙盒 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__
的路径,从而返回任何模块。
对于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)>