python中错误useofeval_Python中的eval

本文最后更新于2015年8月2日,已超过 1 年没有更新,如果文章内容失效,还请反馈给我,谢谢!

缘由:

在Freebuf上看到的两篇文章:Python eval的常见错误封装及利用原理、Python安全编码与代码审计,里面涉及到了对Python的eval函数的说明和讲解,之后我又去网上搜了一些资料,整理成了这篇文章。

搜索关键字:

python eval literal_eval

参考链接:

# Python中的eval是用来干嘛的?

# eval是非常危险的

# 用 eval / ast.literal_eval 来操作json数据?

# Python eval的常见错误封装及利用原理

参考解答:

问:Python中的eval是用来干嘛的?

答:eval() 将第一个字符串参数解释为Python代码并执行。

==

The eval function lets a python program run python code within itself.eval example (interactive shell):

>>> x = 1

>>> eval('x + 1')

2

>>> eval('x')

1

==

eval() interprets a string as code. The reason why so many people have warned you about using this is because a user can use this as an option to run code on the computer. If you have eval(input()) and os imported, a person could type into input() os.system(‘rm -R *’) which would delete all your files in your home directory. (Assuming you have a unix system). Using eval() is a security hole. If you need to convert strings to other formats, try to use things that do that, like int().

==

与eval()函数相比,ast.literal_eval()函数仅认为少数(安全的)Python语法操作是合法的:

The string or node provided may only consist of the following Python literal structures: strings, numbers, tuples, lists, dicts, booleans, and None.

Passing __import__(‘os’).system(‘rm -rf /’) into ast.literal_eval() will raise an error, but eval() will happily wipe your drive.

Since it looks like you’re only letting the user input a plain dictionary, use ast.literal_eval(). It safely does what you want and nothing more.

==

You cannot secure eval with a blacklist approach like this. See Eval really is dangerous for examples of input that will segfault the CPython interpreter, give access to any class you like, and so on.

==

In [1]: print eval("__import__('os').getcwd()", {})

D:\

In [2]: print eval("__import__('os').remove('file')", {"__builtins__": {}})

---------------------------------------------------------------------------

NameError Traceback (most recent call last)

in ()

----> 1 print eval("__import__('os').remove('file')", {"__builtins__": {}})

in ()

NameError: name '__import__' is not defined

Note that this doesn’t protect you from CPU or memory resource attacks (for example, something like:

>>> eval("'*'*1000000*2*2*2*2*2*2*2*2*2")

will most likely cause your program to run out of memory after a while)

==

下面这段代码则是退出解释器:

>>> s = """

... [

... c for c in

... ().__class__.__bases__[0].__subclasses__()

... if c.__name__ == "Quitter"

... ][0](0)()

... """

>>> eval(s, {'__builtins__':{}})

D:\>

初步理解一下整个过程:

>>> ().__class__.__bases__[0].__subclasses__()

...

...

这句Python代码的意思就是找tuple的class,再找它的基类,也就是object,再通过object找他的子类,具体的子类也如代码中的输出一样。从中可以看到了有file模块,zipimporter模块,是不是可以利用下呢?首先从file入手。

假如用户如果构造:

>>> s1 = """

... [

... c for c in ().__class__.__bases__[0].__subclasses__()

... if c.__name__ == "file"

... ][0]("/etc/passwd").read()()

... """

>>> eval(s1, {'__builtins__':{}})

Traceback (most recent call last):

File "", line 1, in

File "", line 5, in

IOError: file() constructor not accessible in restricted mode

这个restrictected mode简单理解就是Python解释器的沙盒,一些功能被限制了,比如说不能修改系统,不能使用一些系统函数,如file,详情见Restricted Execution Mode,那怎么去绕过呢?这时我们就想到了zipimporter了,假如引入的模块中引用了os模块,我们就可以进行利用了。也就是说刚才的safe_eval其实是不安全的。

如何正确使用

使用ast.literal_eval

如果仅仅是将字符转为dict,可以使用json格式

=EOF=

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值