Petr Viktorin
September 27, 2012
360

# 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

2. ### \$ 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().
3. ### import os import math f = raw_input ( " Zadej

funkci : " ) for x in range ( 5 ) : print " x = %s , y = %s " % ( x , eval ( f ) )
4. ### Zadej funkci: x * 5 x = 0, y =

0 x = 1, y = 5 x = 2, y = 10 x = 3, y = 15 x = 4, y = 20
5. ### 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
6. ### 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
7. ### 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
8. ### 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')

10. ### \$ 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.
11. ### >>> import math >>> eval ( "math . sin (

3 . 1 4 1 ) " ) 0.0005926535550994539
12. ### >>> 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 deﬁned
13. ### >>> import math >>> import os >>> eval ( "math

. sin ( 3 . 1 4 1 ) " , dict ( math=math) ) 0.0005926535550994539
14. ### >>> 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 deﬁned

16. ### >>> import math >>> import os >>> eval ( "

dir ( ) " ) [ ' __builtins__ ' , '__doc__ ' , '__name__ ' , ' __package__ ' , 'math ' , ' os ' ]
17. ### >>> import math >>> import os >>> eval ( "

dir ( ) " ) [ ' __builtins__ ' , '__doc__ ' , '__name__ ' , ' __package__ ' , 'math ' , ' os ' ] >>> eval ( " dir ( ) " , dict (math=math) ) [ ' __builtins__ ' , 'math ' ]
18. ### >>> dir ( __builtins__ ) [ . . . ,

' abs ' , ' a l l ' , ' any ' , ' apply ' , ' basestring ' , ' bin ' , ' bool ' , ' buffer ' , ' bytearray ' , ' bytes ' , ' callable ' , ' chr ' , 'cmp ' , . . . , ' vars ' , ' xrange ' , ' zip ' ]
19. ### >>> 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 ...
20. ### >>> eval ( "open ( ' / etc / passwd

' ) . read ( ) " , dict ( __builtins__ = { } ) ) Traceback ( most recent c a l l l a s t ) : . . . NameError : name 'open' is not deﬁned
21. ### >>> eval ( "open ( ' / etc / passwd

' ) . read ( ) " , dict ( __builtins__ = { } ) ) Traceback ( most recent c a l l l a s t ) : . . . NameError : name 'open' is not deﬁned >>> eval ( " abs(−5) " , dict ( __builtins__ = { } , abs=abs ) ) 5

3 + x
25. ### Co není výraz? def f ( x ) : return

3 + x for x in range (10) : print x
26. ### Co není výraz? def f ( x ) : return

3 + x for x in range (10) : print x x = 3
27. ### 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

30. ### def f ( x ) : return 3 + x

f = ( lambda x : 3 + x ) !

32. ### x = 3 * 8 foobar ( x ) (

lambda x=3 ** 8: foobar ( x ) ) ( )

34. ### for x in range (10) : print x [ sys

. stdout . write ( '%s \ n ' % x ) for x in range (10) ]
35. ### def f ( x ) : return 3 + x

for i in range (10) : print f ( i )
36. ### 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) ] ) ( ) !
37. ### class T( object ) : def __init__ ( self ,

p) : s e l f . p = p
38. ### 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) } )

40. ### import os os . system ( " echo pwned" )

__import__ ( ' os ' ) . system ( " echo pwned" ) !
41. ### import os os . system ( " echo pwned" )

( lambda os=__import__ ( ' os ' ) : os . system ( " echo pwned" ) ) ( )

43. ### Téměř jakýkoli program se dá převést na jediný výraz eval()

vyhodnotí jakýkoli výraz
44. ### 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__...

46. ### >>> (42) . bit_length ( ) 6 >>> dir (42)

[ . . . , '__add__ ' , ' __class__ ' , '__doc__ ' , ' __hash__ ' , ' __str__ ' , ' bit_length ' , . . . ]
47. ### >>> (42) . bit_length ( ) 6 >>> dir (42)

[ . . . , '__add__ ' , ' __class__ ' , '__doc__ ' , ' __hash__ ' , ' __str__ ' , ' bit_length ' , . . . ] >>> (42) . __class__ <type ' int ' >
48. ### >>> (42) . __class__ . mro ( ) [ <

type ' int ' > , <type ' object ' >]
49. ### >>> (42) . __class__ . mro ( ) [ <

type ' int ' > , <type ' object ' >] >>> ' 42 ' . __class__ . mro ( ) [ < type ' str ' > , <type ' basestring ' > , <type ' object ' >]
50. ### >>> (42) . __class__ . mro ( ) [ <

type ' int ' > , <type ' object ' >] >>> ' 42 ' . __class__ . mro ( ) [ < type ' str ' > , <type ' basestring ' > , <type ' object ' >] >>> (42) . __class__ . mro ( ) [ −1] <type ' object ' >
51. ### >>> (42) . __class__ . mro ( ) [ −1]

<type 'object'>
52. ### >>> (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'>, ...]
53. ### >>> [ c for c in ( ( 4 2

) . __class__ . mro ( ) [ −1]. __subclasses__ ( ) ) i f c . __name__ == ' f i l e ' ] [ 0 ] <type 'ﬁle'>
54. ### >>> [ 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 . . .
55. ### ( 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 , " " ) , { } ) ( ) ) ( )

57. ### Ale eval()ovaný kód se dá předem vyčistit!!!! Znáte problémy s

os.system? SQL injection? XSS?
58. ### 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?
59. ### 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á!!!!

63. ### Věřím svým uživatelům! Opravdový modul Dělám kalkulačku! pyparsing, PLY Chci

načíst dict/list! ast.literal_eval
64. ### 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
65. ### 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()
66. ### Pozor na to, že eval se zákeřně schovává ve funkci

input! input(x) ⇔ eval(raw_input(x))