有没有办法遍历所有可导入的模块

时间:2011-03-14 01:57:45

标签: python import module traversal

我需要阻止一些模块,我需要知道某个模块是否不导入它。所以我需要一种遍历所有模块的方法来查看模块是否有子模块,我需要阻止它。

有没有办法检查所有已安装的模块是否存在需要阻止的模块?我不需要跨平台解决方案。

4 个答案:

答案 0 :(得分:2)

听起来你正试图build a sandbox。 Python wiki列出了一些good approaches

我看了一下你的webapp,这很容易被黑客攻击:

  • 您可以导入ctypes.utillogging等模块或import os, sys的数百个其他模块。
  • 您甚至可以直接导入模块,如x = [__import__("os")]
  • __builtins__['__import__']("os")也适用

这些只是我尝试过的第一件事。

如果您真的想这样做,那么唯一合理的方法就是建立一个白名单的安全模块。您必须通过每个模块的源并确定它们是否仅导入安全模块。

我不认为你可以在不改变Python解释器的情况下达到任何真正的安全性。有可能不那么明显的方法来掌握这些模块,你必须找到它们。

答案 1 :(得分:1)

这将阻止@Jochen观察到的行为(假设您更充分地填充列表)

def __import__(name, globals={}, locals={}, fromlist=[], level=-1, oldfunc=__import__):
    checklist = fromlist[:]
    checklist.extend(name.split('.'))
    for check in checklist:
        if check in ('os', 'sys'):
            print 'Uh-uh I\'m better than that...'
            return
    oldfunc(name, globals, locals, fromlist, level)

在您的网站上试用它:


>>> def __import__(name, globals={}, locals={}, fromlist=[], level=-1, oldfunc=__import__):
    checklist = fromlist[:]
    checklist.extend(name.split('.'))
    for check in checklist:
        if check in ('os', 'sys'):
            print 'Uh-uh I\'m better than that...'
            return
    oldfunc(name, globals, locals, fromlist, level)
>>> __import__('os')
Uh-uh I'm better than that...
>>> x = [__import__('os')]
Uh-uh I'm better than that...
>>>  

但它不会更改默认的import行为。看起来你正在停止在那里写一个名为'os'的文字。如果你能找到一种编辑实际import行为的方法来调用这个函数(我不希望这甚至是可能的,但值得研究)那么你可以允许文字的名字沿着危险的方向行进进口 - 以及允许人们使用他们喜欢的变量名称,这将使你更难弄清楚你正在采取什么措施来防止进口,从而绕过它......

答案 2 :(得分:1)

如果您正在尝试沙箱Python,我所知道的唯一真正的实现提供了这个没有OS支持的实现PyPy。一年或两年前在python-dev上有一个讨论沙盒的线程,人们通过窥视堆栈来获取无法进行本地导入的模块,字节码操作和其他一些东西,从而打破了所有尝试。

还讨论了一些额外的答案here

答案 3 :(得分:0)

如果您只想阻止模块,您可以使用sys.path变量并使用它来确保它只包含列入白名单的模块(或排除列入黑名单的模块)。这样,Python解释器将无法找到不允许的模块,因此任何导入都将失败。

http://docs.python.org/tutorial/modules.html(参见6.1.2:“模块搜索路径”)