Is there a way to traverse all modules that can be imported
I need to block some modules and I need to know if some module don't import it. So I need a way to traverse all modules to see if a module have sub module, that I need to block.
Is there a way to check all installed modules for existence of modules I need to block? I do开发者_C百科n't need cross-platform solution.
Sounds like you're trying to build a sandbox. The Python wiki lists some good approaches.
I took a look at your webapp and it's quite easy to hack:
- you can import modules like
ctypes.util
orlogging
or hundreds of others thatimport os, sys
. - you can even import the modules directly like
x = [__import__("os")]
__builtins__['__import__']("os")
works too
and those are just the first things I tried.
If you really want to do this then the only reasonable approach is to built a whitelist of safe modules. You have to though the sources for each module and determine if they import only safe modules.
I don't think you can reach any kind of real security without changing the Python interpreter though. There are probably way less obvious ways to get a hold of these modules and you'd have to find them all.
This will prevent the behaviour @Jochen observed (assuming you populate your list a little more fully)
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)
Trying it on your site gives:
>>> 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...
>>>
It doesn't however change the default import
behaviour. It looks like you're stopping there from being a literal with the name 'os' in it. If you can find a way of editing the actual import
behaviour to call this function (I'm not hopeful that this is even possible, but it's worth looking into) then you can allow literals with names along the lines of dangerous imports - as well as allowing people to use variable names that they like, this will make it harder to work out what you're doing to prevent imports, and therefore getting around it...
If you are trying to sandbox Python, the only real implementation I know of that provides this without OS support is PyPy. There was a thread on python-dev a year or two ago discussing sandboxing and people broke all the attempts by doing things like peeking into the stack to obtain modules that couldn't be locally imported, bytecode manipulation and a hundred other things.
A couple of extra answers are discussed here as well.
If you just want to block modules, you may be able to play with sys.path variable and use it to make sure that it only contains whitelisted modules (or excludes blacklisted ones). This way the Python interpreter won't be able to find disallowed modules and therefore any import of those will fail.
http://docs.python.org/tutorial/modules.html (see 6.1.2: “The Module Search Path”)
精彩评论