eval()介绍
功能:将字符串str当成有效的表达式来求值并返回计算结果。
语法: eval(source[, globals[, locals]])
参数:
- source:必填,一个Python表达式的字符串或者compile()返回的代码对象
- globals:非必填,必须是dictionary
- locals:非必填,任何映射对象,默认与globals参数一致
如果globals,locals参数都不指定,表达式将在eval调用的环境中执行,即默认为globals()和locals()函数中包含的模块和函数,这就使得eval方法存在一定的安全风险。
eval()的安全性
输出
假设某配置以列表形式存储在txt文件中,现需要将配置项读出并添加1个元素。基于这种背景上述function函数实现将txt文本中字符串形式的list数据,转换为列表,再将‘5’添加至列表中。
这段代码看上去满足功能需求,也能够正常运行,没有什么问题,但是确存在很大的安全隐患。
eval()函数将任何字符串当做表达式处理,这就意味着有漏洞可寻,假设上面栗子配置项或者用户输入的是"__import__('os').system ('dir')",输出又会是什么呢?会看下它打印了当前目录的所有文件列表,如下
那么如果有人输入"__import__('os').system ('del /f /s /q *')",又会怎样呢?这里不要进行尝试哦,这会使得当前目录的所有文件在不需要确认的前提下全部删除!是不是很可怕。。。
eval()的辩解
上面的栗子,让我们感觉eval函数还是不用的好,特别是在网络环境中,但eval()函数的其余两个参数表示不服,globals、locals函数干嘛用的?然而即使通过globals、locals参数限制了eval()的范围,也无法根本上解决安全性的问题,比如输入:
输出
发现当输入如下字符串时, [q for q in ().__class__.__bases__[0].__subclasses__() if q.__name__=='Quitter'][0](0)() 程序未执行后续代码就直接退出了。
当然除此之外,还有很多种方式可以通过eval本身的安全漏洞达到一些恶意的企图,因此尽量避免使用eval函数。
除了eval函数 还有更好的选择
推荐使用ast.literal_eval(),它会判断需要计算的内容计算后是否是安全、合法的python类型,如果是则进行运算,否则会直接抛出异常。
输出:
转载请说明,若对你有帮助,点赞支持哦