eval()、exec()与execfile()
eval(expression[, globals[, locals]])
eval()函数执行一个python表达式字符串并返回表达式执行后的结果:
>>> x = 1
>>> eval('x + 1')
2
expression参数为一个表达式字符串,globals和locals为可选的参数,globals必须是一个字典对象,locals可为任意映射对象,分别用作代码执行的全局和局部命名空间。
globals和locals参数缺失的时候,表达式会使用当前环境的全局和局部命名空间值:
>>> x = 1
>>> g = {'x' : 2}
>>> eval('x + 1', g)
3
>>> eval('x + 1')
2
eval()函数在数据类型转换中很有用,可以将字符串转换成字典、列表等:
>>> exp = '[1,2,3,4]'
>>> eval(exp)
[1, 2, 3, 4]
>>> exp = '{"a" : 1}'
>>> eval(exp)
{'a': 1}
eval()也可以使用模块:
>>> import os
>>> eval('os.getcwd()')
'/home/user'
当然,eval不能直接对模块进行操作,如果非要使用eval进行import:
>>> eval('__import__("os").getcwd()')
'/home/user'
这一般用于根据客户需求动态的调用不同的模块。
其它的用做计算器啥的也不在话下,不过eval函数也不能滥用,比如要获取用户的输入并求值eval(raw_input()),
这种情况下,用户输入open(__file__).read()可直接把原文件读出来了。
要安全的使用eval()函数,可以使用globals和locals两个参数来设置白名单,当参数缺失的时候,表达式会使用当前环境的全局和局部命名空间值,即globals()和locals()中包含的模块和函数:
>>> import os
>>> 'os' in globals()
True
>>> eval('os.getcwd()')
'/home/user'
将globals和locals两个参数设置为空:
>>> 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
但使用内置函数却可以绕过白名单:
>>> eval('abs(10)', {}, {})
10
>>> eval('__import__("os").getcwd()', {}, {})
'/home/user'
可以看下globals():
>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, '__package__': None}
__builtins__设置着python的内置函数,下面的写法是一样的:
>>> abs(10)
10
>>> __builtins__.abs(10)
10
将__builtins__设置为空则可避免内置函数的滥用:
>>> 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
看情况这下是安全了,但是还是可以绕过的:
>>> ().__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'>]
通过tuple的class找到它的基类,也就是object,然后再找到object的各种子类,从中可以看到很多模块。
使用Quitter退出解释器:
>>> eval("[x for x in ().__class__.__bases__[0].__subclasses__() if x.__name__== 'Quitter'][0](0)()", {'__builtins__':None})
user:~$
configobj,urllib,urllib2,setuptools等模块中都有os模块的内置:
>>> import configobj
>>> 'os' in configobj.__dict__
True
>>> import urllib2
>>> 'os' in urllib2.__dict__
True
>>> import setuptools
>>> 'os' in setuptools.__dict__
True
使用zipimport通过egg文件导入这些模块就可以使用os模块了:
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})
以上可以看出,eval()函数的漏洞还是很多的,如果只是用来做类型转换,可以使用ast.literal_eval 代替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]])
类似的,exec函数执行一个包含python代码的字符串,execfile则执行一个文件,后两个参数与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))
给eval或者exec函数传递字符串时,解析器首先会把字符串编译成字节码,为避免消耗资源,可以使用compile函数将字符串预编译:
compile(str, filename, kind)
str是要预编译的字符串,filename为字符串所在的文件,kind参数为single时代表一条语句,exec代表一组语句,eval代表一个表达式
>>> s = 'for i in [1, 2, 3]: print i'
>>> c = compile(s, '', 'exec')
>>> exec(c)
1
2
3
>>> s2 = '1+1'
>>> c2 = compile(s2, '', 'eval')
>>> eval(c2)
2
eval执行exec类型的预编译字节码时,会返回None:
>>> s2 = '1+1'
>>> c2 = compile(s2, '', 'exec')
>>> print eval(c2)
None
以前看到过一个案例,使用eval转换不规则的json数据:
>>> blog = "{url : 'www.example.com'}"
上面url缺少引号,使用eval和json.loads()均会报错。
>>> 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
使用eval时,eval会将url视为变量名并试图在globals和locals中寻找url的值,添加一下globals参数:
>>> eval(blog, {'url' : 'url'})
{'url': 'www.example.com'}
所以,现在要做的是就是建立一个类dict的映射对象,其中value的值需要与key值相同,可以使用type函数来建立:
>>> ValueFromKey = type('ValueFromKey', (dict,), dict(__getitem__ = lambda self,k : k))
>>> eval(blog, ValueFromKey())
{'url': 'www.example.com'}
在新建的type对象基类元祖中包含下dict,然后在对象的dict中定义一下__getitem__方法,使value值与key值一致即可。
eval()、exec()与execfile()的更多相关文章
- python中eval, exec, execfile,和compile [转载]
eval(str [,globals [,locals ]])函数将字符串str当成有效Python表达式来求值,并返回计算结果. 同样地, exec语句将字符串str当成有效Python代码来执行. ...
- python中eval, exec, execfile,和compile
eval(str [,globals [,locals ]])函数将字符串str当成有效Python表达式来求值,并返回计算结果. 同样地, exec语句将字符串str当成有效Python代码来执行. ...
- 执行字符串或注释代码段的方法(eval、exec、execfile)
eval:计算字符串中的表达式exec:执行字符串中的语句execfile:用来执行一个文件 需注意的是,exec是一个语句,而eval()和execfile()则是内建built-in函数. 1 2 ...
- bash,bg,bind,break,builtin,caller,compgen, complete,compopt,continue,declare,dirs,disown,enable,eval,exec,expo
bash,bg,bind,break,builtin,caller,compgen, complete,compopt,continue,declare,dirs,disown,enable,eval ...
- eval & exec(绕过长度限制思路学习)
eval & exec知识点记录--原文章phithon,只是记录一下我自己的学习过程. 1.eval & exec if(strlen($param)<17 && ...
- python-内置函数-compile,eval,exec
#将字符串,编译成python代码 compile()#执行,有返回值,执行表达式并获取结果 eval()#执行python代码,无返回值,接收:代码或者字符串 exec() s = "pr ...
- Python 执行字符串表达式函数(eval exec execfile)
eval:计算字符串中的表达式 exec:执行字符串中的语句 execfile:用来执行一个文件 在python 2中exec是语句,在python3中exec变为函数,后面要跟括号.在python3 ...
- eval、exec、execfile
# -*- coding: utf-8 -*- #python 27 #xiaodeng #http://blog.csdn.net/azhao_dn/article/details/6921654 ...
- Python中的eval(),exec()以及其相关函数
1. eval函数 函数的作用: 计算指定表达式的值.也就是说它要执行的Python代码只能是单个运算表达式(注意eval不支持任意形式的赋值操作),而不能是复杂的代码逻辑,这一点和lambda表达式 ...
随机推荐
- 大数据-05-Spark之读写HBase数据
本文主要来自于 http://dblab.xmu.edu.cn/blog/1316-2/ 谢谢原作者 准备工作一:创建一个HBase表 这里依然是以student表为例进行演示.这里假设你已经成功安装 ...
- qq浏览器默认字体设置
- Windows10上安装Keras 和 TensorFlow-GPU
安装环境: Windows 10 64bit GPU: GeForce gt 720 Python: 3.5.3 CUDA: 8 首先下载Anaconda3的Win10 64bit版,安装Python ...
- 利用JavaCSV API来读写csv文件
http://blog.csdn.net/loongshawn/article/details/53423121 http://javacsv.sourceforge.net/ 转载请注明来源-作者@ ...
- 【Hadoop学习之一】Hadoop介绍
一.概念 Hadoop是一个能够对大量数据进行分布式处理的软件框架,充分利用集群的威力进行高速运算和存储. 二.主要模块Hadoop Common:支持其他Hadoop模块的常用实用程序.Hadoop ...
- 【转】基于 Kylin 的推荐系统效果评价系统
OLAP(联机分析处理)是数据仓库的主要应用之一,通过设计维度.度量,我们可以构建星型模型或雪花模型,生成数据多维立方体Cube,基于Cube可以做钻取.切片.旋转等多维分析操作.早在十年前,SQL ...
- C# 调整控件的Z顺序
当窗口或者容器控件中的控件在布局过程中发生重叠的时候,会出现层次性.Z顺序较大的控件会遮挡Z顺序较小的控件,放在顶层的控件会挡住放在底层的控件. 1.编辑一个这样的窗口(使用Label控件) 2.添加 ...
- linux python虚拟环境 相关的
为什么要用虚拟环境 在使用python开发过程中,各种业务需求多了,导致工程任务多了,难免会碰到不同的工程依赖不同版本库的问题,;或者是在开发的时候不想让物理环境里充斥各种各样的库,引发依赖环境灾难, ...
- 判断是移动端还是PC端
// 判断是移动端还是PC端 $http_user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? strtolower($_SERVER['HTTP_USE ...
- 通过junit/TestNG+java 实现自动化测试
第一步 安装JDK JDk1.7. 下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-188026 ...