[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.