[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: [pygame] Scripting language
BTW, it's perfectly possible to eliminate open() and file() from usability.
The only problem is it requires a separate instance of __bulitins__ (therefore probably a separate interpreter)
Try 1:
>>> def fakeopen (filename, mode = 'r', buffering = 0):
... raise NotImplementedError
...
>>>
>>> __builtins__.open = fakeopen
>>> __builtins__.file = fakeopen
>>> open ('/dev/urandom', 'rb')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in fakeopen
NotImplementedError
Try 2 (no, you don't need another interpreter instance!)
>>> def fakeopen (filename, mode = None, buffering = None):
... raise NotImplementedError
...
>>> newbuiltins = dict (vars (__builtins__))
>>> env = {}
>>> newbuiltins['open'] = fakeopen
>>> newbuiltins['file'] = fakeopen
>>> env['__builtins__'] = newbuiltins
>>> # Try to do something VERBOTEN.
>>> script = "f = open('/dev/random','r'); randombyte = f.read
(1)"
>>> exec script in env
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
File "<stdin>", line 2, in fakeopen
NotImplementedError
>>> # now see what nested exec does..
...
>>>
>>> script = """exec "f = open('/dev/random','r'); randombyte = f.read(1)";"""
>>> exec script in env
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
File "<string>", line 1, in <module>
File "<stdin>", line 2, in fakeopen
NotImplementedError
>>> # still works!
...
Unless there is some way to access open() via modules' __builtins__ attribute, or functions' func_globals attribute..
And there is. But it's caught!
script = """exec "import os; f = os.__builtins__['open']('/dev/random','r'); randombyte = f.read(1);f.close()";"""
>>> exec script in env
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
File "<string>", line 1, in <module>
IOError: file() constructor not accessible in restricted mode
>>>
I am running Python 2.6 here, and evidently setting __builtins__ in a globals dictionary activates restricted mode for anything running in it.
Testing nestedness
>>> # now for extreme convolution
...
>>> script = """exec "f = open('/dev/random','r'); randombyte = f.read(1);f.close()" in os.__builtins__"""
>>> exec script in env
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
File "<string>", line 1, in <module>
IOError: file() constructor not accessible in restricted mode
:D
Testing silly degree of nestedness:
>>> #and ultimate convolution
...
>>> script = """exec "exec \\\"f = open('/dev/random','r'); randombyte =
f.read(1);f.close()\\\"" in os.__builtins__"""
>>> exec script in env
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
File "<string>", line 1, in <module>
File "<string>", line 1, in <module>
IOError: file() constructor not accessible in restricted mode
So that's pretty locked-down (I haven't tested the os module -- get a checkout of SVN python if you want to do that.)
Greg, in Python 2.6:
Python 2.6a0 (trunk:52884, Dec 1 2006, 14:21:57)
[GCC 4.0.3 (Ubuntu 4.0.3-1ubuntu5)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> (3).__class__.__bases__[0].__subclasses__()[-3]
<type 'deque_reverse_iterator'>
>>> (3).__class__.__bases__[0].__subclasses__()[-29]
<type 'file'>
>>> # It's a nice hack, but it doesn't help you evade restrictions:
>>> exec "(3).__class__.__bases__[0].__subclasses__()[-29]('/dev/urandom')" in env
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
IOError: file() constructor not accessible in restricted mode
The two other major issues are looping-forever (which can't be fixed really, except by restricting execution time) and memory usage (I accidentally created a infinite loop today that expanded Python's memory usage to 500mb). Greg's idea of running as a seperate process is good for addressing those.
Re: imports -- probably the only fully safe way is to prohibit them completely, and pre-import chosen safe modules for your scripts' use.