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

0 投票
4 回答
779 浏览
提问于 2025-04-16 13:38

我需要阻止一些模块的使用,并且想知道某个模块是否没有引入这些模块。所以我需要一种方法,能遍历所有模块,看看某个模块是否有我需要阻止的子模块。

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

4 个回答

1

如果你想要在一个安全的环境中运行Python代码,我知道的唯一一个真正能做到这一点而不需要操作系统支持的工具是PyPy。大约一两年前,python-dev上有个讨论关于沙箱的帖子,大家尝试了很多方法,但都被人们打破了,比如通过查看调用栈来获取那些不能本地导入的模块,或者对字节码进行操作,还有很多其他的方式。

另外,还有一些额外的答案可以在这里找到。

2

听起来你想要建立一个沙盒环境。Python的维基上列出了一些不错的方法

我看了你的网页应用,发现它很容易被攻击:

  • 你可以导入像ctypes.utillogging这样的模块,还有成百上千个其他模块,它们都可以通过import os, sys来导入。
  • 你甚至可以直接导入模块,比如x = [__import__("os")]
  • __builtins__['__import__']("os")也可以用

这些只是我尝试的第一些方法。

如果你真的想做到这一点,唯一合理的办法就是建立一个白名单,列出安全的模块。不过,你需要查看每个模块的源代码,确认它们只导入安全的模块。

不过,我觉得如果不改变Python解释器,你是无法达到真正的安全性的。可能还有很多不明显的方法可以获取这些模块,你得把它们都找出来。

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行为,使其调用这个函数(我对这是否可能不抱太大希望,但值得一试),那么你就可以允许一些像危险导入这样的名称字面量,同时也让人们可以使用他们喜欢的变量名,这样就更难判断你是如何防止导入的,从而也就更难绕过这个限制……

撰写回答