Share
Embed
Zákeřný eval()
Zrádnosti funkce eval(), a co použít místo ní. Přednáška pro zářijové PyVo 2012.
Petr Viktorin
September 27, 2012
Transcript
68 slides
-
$ pydoc eval eval(source[, globals[, locals]]) Evaluate the source in
the context of globals and locals. The source may be a string representing a Python expression or a code object as returned by compile(). -
import os import math f = raw_input ( " Zadej
funkci : " ) for x in range ( 5 ) : print " x = %s , y = %s " % ( x , eval ( f ) ) -
Zadej funkci: x * 5 x = 0, y =
0 x = 1, y = 5 x = 2, y = 10 x = 3, y = 15 x = 4, y = 20 -
Zadej funkci: x * 5 x = 0, y =
0 x = 1, y = 5 x = 2, y = 10 x = 3, y = 15 x = 4, y = 20 Zadej funkci: math.sin(x) x = 0, y = 0.0 x = 1, y = 0.841470984808 x = 2, y = 0.909297426826 x = 3, y = 0.14112000806 x = 4, y = -0.756802495308 -
Zadej funkci: x * 5 x = 0, y =
0 x = 1, y = 5 x = 2, y = 10 x = 3, y = 15 x = 4, y = 20 Zadej funkci: math.sin(x) x = 0, y = 0.0 x = 1, y = 0.841470984808 x = 2, y = 0.909297426826 x = 3, y = 0.14112000806 x = 4, y = -0.756802495308 Zadej funkci: x ** 999999 x = 0, y = 0 x = 1, y = 1 -
Zadej funkci: x * 5 x = 0, y =
0 x = 1, y = 5 x = 2, y = 10 x = 3, y = 15 x = 4, y = 20 Zadej funkci: math.sin(x) x = 0, y = 0.0 x = 1, y = 0.841470984808 x = 2, y = 0.909297426826 x = 3, y = 0.14112000806 x = 4, y = -0.756802495308 Zadej funkci: x ** 999999 x = 0, y = 0 x = 1, y = 1 Zadej funkci: open('/etc/passwd').read() x = 0, y = root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin -
Zadej funkci: x * 5 x = 0, y =
0 x = 1, y = 5 x = 2, y = 10 x = 3, y = 15 x = 4, y = 20 Zadej funkci: math.sin(x) x = 0, y = 0.0 x = 1, y = 0.841470984808 x = 2, y = 0.909297426826 x = 3, y = 0.14112000806 x = 4, y = -0.756802495308 Zadej funkci: x ** 999999 x = 0, y = 0 x = 1, y = 1 Zadej funkci: open('/etc/passwd').read() x = 0, y = root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin Zadej funkci: os.system('fire-mah-lazors --target=alderaan') -
$ pydoc eval eval(source[, globals[, locals]]) The globals must be
a dictionary and locals can be any mapping, defaulting to the current globals and locals. If only globals is given, locals defaults to it. -
>>> import math >>> eval ( "math . sin (
3 . 1 4 1 ) " ) 0.0005926535550994539 -
>>> import math >>> eval ( "math . sin (
3 . 1 4 1 ) " ) 0.0005926535550994539 >>> eval ( "math . sin ( 3 . 1 4 1 ) " , { } ) Traceback ( most recent c a l l l a s t ) : . . . NameError : name 'math' is not defined -
>>> import math >>> import os >>> eval ( "math
. sin ( 3 . 1 4 1 ) " , dict ( math=math) ) 0.0005926535550994539 -
>>> import math >>> import os >>> eval ( "math
. sin ( 3 . 1 4 1 ) " , dict ( math=math) ) 0.0005926535550994539 >>> eval ( " os . system ( ' echo pwned ' ) " , dict (math=math) ) Traceback ( most recent c a l l l a s t ) : . . . NameError : name 'os' is not defined -
>>> import math >>> import os >>> eval ( "
dir ( ) " ) [ ' __builtins__ ' , '__doc__ ' , '__name__ ' , ' __package__ ' , 'math ' , ' os ' ] -
>>> import math >>> import os >>> eval ( "
dir ( ) " ) [ ' __builtins__ ' , '__doc__ ' , '__name__ ' , ' __package__ ' , 'math ' , ' os ' ] >>> eval ( " dir ( ) " , dict (math=math) ) [ ' __builtins__ ' , 'math ' ] -
>>> dir ( __builtins__ ) [ . . . ,
' abs ' , ' a l l ' , ' any ' , ' apply ' , ' basestring ' , ' bin ' , ' bool ' , ' buffer ' , ' bytearray ' , ' bytes ' , ' callable ' , ' chr ' , 'cmp ' , . . . , ' vars ' , ' xrange ' , ' zip ' ] -
>>> dir ( __builtins__ ) [ . . . ,
' abs ' , ' a l l ' , ' any ' , ' apply ' , ' basestring ' , ' bin ' , ' bool ' , ' buffer ' , ' bytearray ' , ' bytes ' , ' callable ' , ' chr ' , 'cmp ' , . . . , ' vars ' , ' xrange ' , ' zip ' ] >>> eval ( ' ' ' open ( ' / etc / passwd ' ) . read ( ) ' ' ' , { } ) 'root:x:0:0:root:/root:/bin/bash\n ... -
>>> eval ( "open ( ' / etc / passwd
' ) . read ( ) " , dict ( __builtins__ = { } ) ) Traceback ( most recent c a l l l a s t ) : . . . NameError : name 'open' is not defined -
>>> eval ( "open ( ' / etc / passwd
' ) . read ( ) " , dict ( __builtins__ = { } ) ) Traceback ( most recent c a l l l a s t ) : . . . NameError : name 'open' is not defined >>> eval ( " abs(−5) " , dict ( __builtins__ = { } , abs=abs ) ) 5 -
Co není výraz? def f ( x ) : return
3 + x for x in range (10) : print x -
Co není výraz? def f ( x ) : return
3 + x for x in range (10) : print x x = 3 -
Co není výraz? def f ( x ) : return
3 + x for x in range (10) : print x x = 3 import os a další příkazy: http://docs.python.org/reference/index.html -
def f ( x ) : return 3 + x
f = ( lambda x : 3 + x ) ! -
x = 3 * 8 foobar ( x ) (
lambda x=3 ** 8: foobar ( x ) ) ( ) -
for x in range (10) : print x [ sys
. stdout . write ( '%s \ n ' % x ) for x in range (10) ] -
def f ( x ) : return 3 + x
for i in range (10) : print f ( i ) -
def f ( x ) : return 3 + x
for i in range (10) : print f ( i ) ( lambda f =( lambda x : 3 + x ) , out=sys . stdout . write : [ out ( '%s \ n ' % f ( x ) ) for x in range (10) ] ) ( ) ! -
class T( object ) : def __init__ ( self ,
p) : s e l f . p = p -
class T( object ) : def __init__ ( self ,
p) : s e l f . p = p T = type ( "T" , ( object , ) , { ' __init__ ' : lambda self , p : setattr ( self , 'p ' , p) } ) -
import os os . system ( " echo pwned" )
__import__ ( ' os ' ) . system ( " echo pwned" ) ! -
import os os . system ( " echo pwned" )
( lambda os=__import__ ( ' os ' ) : os . system ( " echo pwned" ) ) ( ) -
Téměř jakýkoli program se dá převést na jediný výraz eval()
vyhodnotí jakýkoli výraz -
Téměř jakýkoli program se dá převést na jediný výraz eval()
vyhodnotí jakýkoli výraz Ještě tak mít ten __import__... -
>>> (42) . bit_length ( ) 6 >>> dir (42)
[ . . . , '__add__ ' , ' __class__ ' , '__doc__ ' , ' __hash__ ' , ' __str__ ' , ' bit_length ' , . . . ] -
>>> (42) . bit_length ( ) 6 >>> dir (42)
[ . . . , '__add__ ' , ' __class__ ' , '__doc__ ' , ' __hash__ ' , ' __str__ ' , ' bit_length ' , . . . ] >>> (42) . __class__ <type ' int ' > -
>>> (42) . __class__ . mro ( ) [ <
type ' int ' > , <type ' object ' >] -
>>> (42) . __class__ . mro ( ) [ <
type ' int ' > , <type ' object ' >] >>> ' 42 ' . __class__ . mro ( ) [ < type ' str ' > , <type ' basestring ' > , <type ' object ' >] -
>>> (42) . __class__ . mro ( ) [ <
type ' int ' > , <type ' object ' >] >>> ' 42 ' . __class__ . mro ( ) [ < type ' str ' > , <type ' basestring ' > , <type ' object ' >] >>> (42) . __class__ . mro ( ) [ −1] <type ' object ' > -
>>> (42) . __class__ . mro ( ) [ −1]
<type 'object'> -
>>> (42) . __class__ . mro ( ) [ −1]
<type 'object'> >>> ( ( 4 2 ) . __class__ . mro ( ) [ −1]. __subclasses__ ( ) ) [<type 'type'>, <type 'weakref'>, ..., <type 'int'>, <type 'basestring'>, ..., <type 'super'>, <type 'xrange'>, ..., <type 'function'>, <type 'classobj'>, ..., <type 'sys.version_info'>, ..., <class 'warnings.catch_warnings'>, ..., <class 'codecs.IncrementalEncoder'>, ...] -
>>> [ c for c in ( ( 4 2
) . __class__ . mro ( ) [ −1]. __subclasses__ ( ) ) i f c . __name__ == ' f i l e ' ] [ 0 ] <type 'file'> -
>>> [ c for c in (42) . __class__ .
mro ( ) [ −1]. __subclasses__ ( ) i f c . __name__ == ' f i l e ' ] [ 0 ] ( ' / etc / passwd ' ) . read ( ) 'root:x:0:0:root:/root:/bin/bash\n . . . -
( lambda fc =( lambda n : [ c for
c in ( ) . __class__ . __bases__ [ 0 ] . __subclasses__ ( ) i f c . __name__ == n ] [ 0 ] ) : fc ( " function " ) ( fc ( " code " ) ( 0 ,0 ,0 ,0 , "KABOOM" , ( ) , ( ) , ( ) , " " , " " ,0 , " " ) , { } ) ( ) ) ( ) -
Ale eval()ovaný kód se dá předem vyčistit!!!! Znáte problémy s
os.system? SQL injection? XSS? -
Ale eval()ovaný kód se dá předem vyčistit!!!! Znáte problémy s
os.system? SQL injection? XSS? Znáte moduly rexec a bastion? -
Ale eval()ovaný kód se dá předem vyčistit!!!! Znáte problémy s
os.system? SQL injection? XSS? Znáte moduly rexec a bastion? ... nedá!!!! -
Věřím svým uživatelům! Opravdový modul Dělám kalkulačku! pyparsing, PLY Chci
načíst dict/list! ast.literal_eval -
Věřím svým uživatelům! Opravdový modul Dělám kalkulačku! pyparsing, PLY Chci
načíst dict/list! ast.literal_eval Čtu/píšu data/koniguraci! YAML, JSON, ConfigParser -
Věřím svým uživatelům! Opravdový modul Dělám kalkulačku! pyparsing, PLY Chci
načíst dict/list! ast.literal_eval Čtu/píšu data/koniguraci! YAML, JSON, ConfigParser Dělám překladač/REPL! compile & exec() -
Pozor na to, že eval se zákeřně schovává ve funkci
input! input(x) ⇔ eval(raw_input(x)) -
? Petr Viktorin @encukou [email protected] Slajdy jsou pod licencí Creative
Commons Attribution-ShareAlike 3.0 http://creativecommons.org/licenses/by-sa/3.0/