您当前的位置:首页 > 计算机 > 编程开发 > Python

Python内置函数eval()用法及其安全问题

时间:09-07来源:作者:点击数:

Python内置函数eval()用来对表达式进行求值:

>>> eval('3+5')

8

>>> a = 3

>>> b = 5

>>> eval('a+b')

8

这个函数在Python 3.x中使用较多,因为在Python 3.x中使用input()函数接收用户输入时一律返回字符串,经常需要进行类型转换,这时候常使用eval()函数,例如:

>>> x = input('Please input:')

Please input:35

>>> x

'35'

>>> type(x)

<class 'str'>

>>> eval(x)

35

>>> type(_)

<class 'int'>

>>> x = input('Please input:')

Please input:[1, 2, 3]

>>> x

'[1, 2, 3]'

>>> type(x)

<class 'str'>

>>> eval(x)

[1, 2, 3]

>>> type(_)

<class 'list'>

但是,需要注意的是,我们无法保证用户总是输入合法的数据,而恶意黑客也是利用一些程序的bug来精心构造非法输入来触发漏洞,从而造成破坏和攻击。

>>> eval("__import__('os').startfile('notepad.exe')") #启动记事本程序

>>> eval('__import__("os").system("dir")') #列出当前目录的文件列表

>>> eval("__import__('os').system('md testtest')") #在当前目录中创建子目录testtest

当然,这里只是一些善意的演示,通过精心构造输入,充分利用Python标准库和扩展库的功能,会实现很多善意或恶意的目的。

如果程序中确实需要用户输入,并且确实需要对用户的输入进行eval(),那么为了保证安全,可以对用户输入进行敏感字符检查和过滤,例如:

>>> x = input('Please input:')

Please input:__import__("os").system("dir")

>>> if '__import__(' in x:  #使用关键字in进行检查

print('error')

error

>>> x = x.replace('__import__(', '***') #使用字符串方法replace()进行过滤和替换

>>> x

'***"os").system("dir")'

>>> eval(x) #如果用户输入中有敏感字符,过滤后会引发异常

Traceback (most recent call last):

  File "<pyshell#24>", line 1, in <module>

    eval(x)

  File "<string>", line 1

    ***"os").system("dir")

     ^

SyntaxError: invalid syntax

或者,也可以采用这样的办法,在程序第一行增加一行eval = print,这样运行程序时会显示用户输入而不是进行求值计算,当反复测试发现用户输入不会带来危害后再删除这一行。

还有一个办法是使用Python标准库ast提供的literal_eval()方法,功能与eval()一致,但更安全,例如:

>>> import ast

>>> ast.literal_eval('3+5') #正常执行

8

>>> ast.literal_eval("__import__('os').startfile('notepad.exe')") #引发异常

Traceback (most recent call last):

  File "<pyshell#31>", line 1, in <module>

    ast.literal_eval("__import__('os').startfile('notepad.exe')")

  File "C:\Python35\lib\ast.py", line 84, in literal_eval

    return _convert(node_or_string)

  File "C:\Python35\lib\ast.py", line 83, in _convert

    raise ValueError('malformed node or string: ' + repr(node))

ValueError: malformed node or string: <_ast.Call object at 0x0000000003539588>

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门