Eval (), exec (), execfile (), evalexecexecfile
Eval(Expression[,Globals[,Locals])
The eval () function executes a python expression string and returns the result after the expression is executed:
>>> x = 1>>> eval('x + 1')2
ExpressionThe parameter is an expression string,GlobalsAndLocalsIs an optional parameter,GlobalsMust be a dictionary object,LocalsIt can be used as a global and local namespace for code execution for any ing object.
GlobalsAndLocalsWhen a parameter is missing, the expression uses the global and local namespace values of the current environment:
>>> x = 1>>> g = {'x' : 2}>>> eval('x + 1', g)3>>> eval('x + 1')2
The eval () function is useful in data type conversion. It can convert strings into dictionaries and lists:
>>> exp = '[1,2,3,4]'>>> eval(exp)[1, 2, 3, 4]>>> exp = '{"a" : 1}'>>> eval(exp){'a': 1}
The eval () module can also be used:
>>> import os>>> eval('os.getcwd()')'/home/user'
Of course, eval cannot directly operate on modules. If you have to use eval for import:
>>> eval('__import__("os").getcwd()')'/home/user'
This is generally used to dynamically call different modules based on customer needs.
Other functions are used as calculators, but eval functions cannot be abused. For example, to obtain user input and evaluate eval (raw_input ()),
In this case, you can directly read the original file by entering open (_ file _). read.
To use the eval () function safely, you can use the globals and locals parameters to set the whitelist. When the parameter is missing, the expression uses the global and local namespace values of the current environment, that is, the modules and functions contained in globals () and locals:
>>> import os>>> 'os' in globals()True>>> eval('os.getcwd()')'/home/user'
Set globals and locals to NULL:
>>> import os>>> eval('os.getcwd()', {}, {})Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module>NameError: name 'os' is not defined
However, using built-in functions can bypass the whitelist:
>>> eval('abs(10)', {}, {})10>>> eval('__import__("os").getcwd()', {}, {})'/home/user'
You can see globals ():
>>> globals(){'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, '__package__': None}
_ Builtins _ set python built-in functions. The following statements are the same:
>>> abs(10)10>>> __builtins__.abs(10)10
If _ builtins _ is set to null, the abuse of built-in functions can be avoided:
>>> eval('abs(10)', {'__builtins__' : None}, {})Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module>NameError: name 'abs' is not defined
This is safe, but it can still be bypassed:
>>> ().__class__.__bases__[0].__subclasses__()[<type 'type'>, <type 'weakref'>, <type 'weakcallableproxy'>, <type 'weakproxy'>, <type 'int'>, <type 'basestring'>, <type 'bytearray'>, <type 'list'>, <type 'NoneType'>, <type 'NotImplementedType'>, <type 'traceback'>, <type 'super'>, <type 'xrange'>, <type 'dict'>, <type 'set'>, <type 'slice'>, <type 'staticmethod'>, <type 'complex'>, <type 'float'>, <type 'buffer'>, <type 'long'>, <type 'frozenset'>, <type 'property'>, <type 'memoryview'>, <type 'tuple'>, <type 'enumerate'>, <type 'reversed'>, <type 'code'>, <type 'frame'>, <type 'builtin_function_or_method'>, <type 'instancemethod'>, <type 'function'>, <type 'classobj'>, <type 'dictproxy'>, <type 'generator'>, <type 'getset_descriptor'>, <type 'wrapper_descriptor'>, <type 'instance'>, <type 'ellipsis'>, <type 'member_descriptor'>, <type 'file'>, <type 'PyCapsule'>, <type 'cell'>, <type 'callable-iterator'>, <type 'iterator'>, <type 'sys.long_info'>, <type 'sys.float_info'>, <type 'EncodingMap'>, <type 'fieldnameiterator'>, <type 'formatteriterator'>, <type 'sys.version_info'>, <type 'sys.flags'>, <type 'sys.getwindowsversion'>, <type 'exceptions.BaseException'>, <type 'module'>, <type 'imp.NullImporter'>, <type 'zipimport.zipimporter'>, <type 'nt.stat_result'>, <type 'nt.statvfs_result'>, <class 'warnings.WarningMessage'>, <class 'warnings.catch_warnings'>, <class '_weakrefset._IterationGuard'>, <class '_weakrefset.WeakSet'>, <class '_abcoll.Hashable'>, <type 'classmethod'>, <class '_abcoll.Iterable'>, <class '_abcoll.Sized'>, <class '_abcoll.Container'>, <class '_abcoll.Callable'>, <class 'site._Printer'>, <class 'site._Helper'>, <type '_sre.SRE_Pattern'>, <type '_sre.SRE_Match'>, <type '_sre.SRE_Scanner'>, <class 'site.Quitter'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>, <type 'operator.itemgetter'>, <type 'operator.attrgetter'>, <type 'operator.methodcaller'>, <type 'functools.partial'>, <type 'MultibyteCodec'>, <type 'MultibyteIncrementalEncoder'>, <type 'MultibyteIncrementalDecoder'>, <type 'MultibyteStreamReader'>, <type 'MultibyteStreamWriter'>, <type 'time.struct_time'>, <type '_ssl._SSLContext'>, <type '_ssl._SSLSocket'>, <type 'cStringIO.StringO'>, <type 'cStringIO.StringI'>, <class 'socket._closedsocket'>, <type '_socket.socket'>, <type 'method_descriptor'>, <class 'socket._socketobject'>, <class 'socket._fileobject'>, <type '_thread._localdummy'>, <type 'thread._local'>, <type 'thread.lock'>, <type 'collections.deque'>, <type 'deque_iterator'>, <type 'deque_reverse_iterator'>, <type 'itertools.combinations'>, <type 'itertools.combinations_with_replacement'>, <type 'itertools.cycle'>, <type 'itertools.dropwhile'>, <type 'itertools.takewhile'>, <type 'itertools.islice'>, <type 'itertools.starmap'>, <type 'itertools.imap'>, <type 'itertools.chain'>, <type 'itertools.compress'>, <type 'itertools.ifilter'>, <type 'itertools.ifilterfalse'>, <type 'itertools.count'>, <type 'itertools.izip'>, <type 'itertools.izip_longest'>, <type 'itertools.permutations'>, <type 'itertools.product'>, <type 'itertools.repeat'>, <type 'itertools.groupby'>, <type 'itertools.tee_dataobject'>, <type 'itertools.tee'>, <type 'itertools._grouper'>, <class 'threading._Verbose'>, <class 'string.Template'>, <class 'string.Formatter'>, <type 'CArgObject'>, <type '_ctypes.CThunkObject'>, <type '_ctypes._CData'>, <type '_ctypes.CField'>, <type '_ctypes.DictRemover'>, <type 'Struct'>, <class 'ctypes.CDLL'>, <class 'ctypes.LibraryLoader'>, <type 'cPickle.Unpickler'>, <type 'cPickle.Pickler'>, <class 'idlelib.rpc.SocketIO'>, <class 'idlelib.rpc.RemoteObject'>, <class 'idlelib.rpc.RemoteProxy'>, <class 'idlelib.rpc.RPCProxy'>, <class 'idlelib.rpc.MethodProxy'>, <type '_io._IOBase'>, <type '_io.IncrementalNewlineDecoder'>, <class 'subprocess.Popen'>, <class 'webbrowser.BaseBrowser'>, <class 'idlelib.tabbedpages.Page'>, <class 'idlelib.EditorWindow.HelpDialog'>, <type '_hashlib.HASH'>, <type '_random.Random'>, <class 'idlelib.EditorWindow.EditorWindow'>, <class 'idlelib.EditorWindow.IndentSearcher'>, <class 'idlelib.run.Executive'>]
Find its base class, that is, object, through the tuple class, and then find the various subclasses of the object, from which you can see many modules.
Use Quitter to exit the interpreter:
>>> eval("[x for x in ().__class__.__bases__[0].__subclasses__() if x.__name__== 'Quitter'][0](0)()", {'__builtins__':None})user:~$
Configobj, urllib, urllib2, setuptools, and other modules all have built-in OS modules:
>>> import configobj>>> 'os' in configobj.__dict__True>>> import urllib2>>> 'os' in urllib2.__dict__True>>> import setuptools>>> 'os' in setuptools.__dict__True
Use zipimport to import these modules through the egg file to use the OS module:
eval("[x for x in ().__class__.__bases__[0].__subclasses__() if x.__name__ == 'zipimporter'][0]('/path/to/configobj-5.0.5-py2.7.egg').load_module('configobj').os.getcwd()", {'__builtins__':None})
As you can see above, there are still many eval () function vulnerabilities. If it is only used for type conversion, you can use ast. literal_eval instead of eval:
>>> import ast>>> ast.literal_eval('[1, 2, 3]')[1, 2, 3]>>> ast.literal_eval('abs(10)')Traceback (most recent call last): File "<pyshell#12>", line 1, in <module> ast.literal_eval('abs(10)') File "C:\Python27\lib\ast.py", line 80, in literal_eval return _convert(node_or_string) File "C:\Python27\lib\ast.py", line 79, in _convert raise ValueError('malformed string')ValueError: malformed string>>> eval('abs(10)')10
Exec(Str[,Globals[,Locals])
Execfile(Filename[,Globals[,Locals])
Similarly, the exec function executes a string containing python code, while the execfile executes a file, and the last two parameters are similar to eval.
>>> a = [1, 2, 3, 4]>>> exec('for i in a: print i')
activate_this = '/path/to/env/bin/activate_this.py'execfile(activate_this, dict(__file__=activate_this))
When passing a string to the eval or exec function, the parser first compiles the string into bytecode. To avoid resource consumption, you can use the compile function to pre-compile the string:
Compile(Str, filename, kind)
Str is the string to be precompiled. filename is the file where the string is located. The kind parameter is a statement in the single era table. exec represents a group of statements, and eval represents an expression.
>>> s = 'for i in [1, 2, 3]: print i'>>> c = compile(s, '', 'exec')>>> exec(c)123>>> s2 = '1+1'>>> c2 = compile(s2, '', 'eval')>>> eval(c2)2
When eval executes the exec pre-compiled bytecode, it returns None:
>>> s2 = '1+1'>>> c2 = compile(s2, '', 'exec')>>> print eval(c2)None
I have seen a case in the past, using eval to convert irregular json data:
>>> blog = "{url : 'www.example.com'}"
If quotation marks are missing from the above url, an error is returned when eval and json. loads () are used.
>>> eval(blog)Traceback (most recent call last): File "<pyshell#27>", line 1, in <module> eval(blog) File "<string>", line 1, in <module>NameError: name 'url' is not defined
When eval is used, eval regards the url as the variable name and tries to find the url value in globals and locals and add the globals parameter:
>>> eval(blog, {'url' : 'url'}){'url': 'www.example.com'}
Therefore, we need to create a dict-like ing object. The value must be the same as the key value. You can use the type function to create a ding object:
>>> ValueFromKey = type('ValueFromKey', (dict,), dict(__getitem__ = lambda self,k : k))>>> eval(blog, ValueFromKey()){'url': 'www.example.com'}
The new type object's base class ancestor contains dict, and then defines the _ getitem _ method in the object's dict to make the value consistent with the key value.