提醒!Python 的 pickle 模块可能导致命令执行
你好,我是征哥,提到 Python 的 pickle 模块,我经常用它保存运行时的对象,以便重启程序后可以恢复到之前的状态。今天发现了它在恢复 Python 对象时存在远程命令执行的安全问题,所以后面如果你的数据来自用户输入,那最好不用 pickle,用 json,官方文档也有警告和建议:
接下来来看一下它是如何导致命令执行的。
Python 的 pickle 可以很方便的把 Python 的对象以二进制的形式保存在文件中(封存),也很容易恢复(解封):
import pickle
x = [1,2,3]
pickle.dump(x,open("test.pkl","wb"))
y = pickle.load(open("test.pkl","rb"))
assert x == y
上面的代码 x 是一个列表,它是安全的,假如 x 是黑客在浏览器端发送的数据,他可以精心构造出这样一个类 Exp,里面可能有各种危险的命令,假如是一个 ls -l
这样的信息收集:
class Exp(object):
def __reduce__(self):
return (os.system,('ls -l',))
x = Exp()
pickle.dump(x,open("test.pkl","wb"))
y = pickle.load(open("test.pkl","rb"))
assert x == y
执行上面的代码,就会发现 ls -l 已经执行:
这里来解释一下魔法函数 __reduce__
:
首先来看一下官方的函数说明:
其中红色框里面是本例子中用到的情形,要注意的是,魔法函数__reduce__
会在 unpickling(解封) 时调用,用于自定义对象的解封方式,如果返回的是元组,那第一个必须是函数,第二个就是函数的参数,而且这个函数会被调用。
因此 os.system('ls -l')
被执行。
最后的话
Python 标准库的漏洞还真的不多,vulhub[1] 上关于 Python 标准库的漏洞也就 3 个:PIL 2 个,Pickle 1 个,感兴趣可以研究下。本文分享了 Pickle 的安全问题,希望给你写代码的时候提个醒,如有帮助,还请关注一下,欢迎留言讨论。
vulhub: https://github.com/vulhub/vulhub/tree/master/python
评论