某些Python函数不应该被使用,或者应该谨慎使用。Python的文档通常包括一个关于危险的注释,但并不总是完全说明为什么这个函数是有风险的。我们将讨论一些危险类别的Python函数和一些替代方案。如果你看到这些在野外使用,这可能不是坏的,但我们应该密切关注他们的使用。

卡里萨·桑多瓦尔的插图
命令注射系列
第一组危险的Python函数围绕着信任用户提供的输入并将其管理到一个shell中。
为什么它们有用
有时您需要发送一个命令行应用程序,使用subprocess.call()和设置使用Python的子进程模块很方便shell=True。
os.system()并且 os.popen*()自Python 2.6以来已被弃用,有利于子进程模块。他们有一个简单的API,他们已经有一段时间了,所以你可能会遇到它们在旧的应用程序。
为什么他们是危险的
使用shell=True(或任何类似的面向命令行工具os),如果有人制作输入以发出与您想要的命令不同的命令,可能会使您面临安全隐患。
一个危险的例子
假设我们要编写一个函数来将用户指定的视频文件转码为不同的格式。我们要求用户在磁盘上找到文件,然后通过ffmpeg运行它来转码。什么可能出错?
import subprocess def transcode_file(): filename = raw_input(’Please provide the path for the file to transcode: ’) command = ’ffmpeg -i "{source}" output_file.mpg’.format(source=filename) subprocess.call(command, shell=True) # a bad idea!
如果某人提供了一个名称如下的文件"; rm -rf /呢?如果主机作为特权用户运行Python进程,那么可以删除机器上的所有文件。那很糟。
使用什么
subprocess与shell=False。它可以保护您免受与外壳管道命令相关的大部分风险。如果你走这条路线, shlex.split() 可以更容易地准备命令(这是Python文档推荐的)。
sh - 用于向其他应用程序发出命令。sh由于引用变量的方式,我之前发出复杂命令有一些麻烦。也就是说,如果它适用于你的用例,那就去吧!
如果你必须使用它们...
逃避你的变数!pipes.quote()如果您使用的是Python 2.x,或者shlex.quote() 使用Python 3.3或更新版本,则可以使用 它 。
为什么它们有用
exec()并将 eval()字符串转成可执行代码。它们可以是有用的,特别是如果你是控制输入的人。作为一个例子,我之前已经用来eval评估一个大的类似字典的字符串到一个字典。
为什么他们是危险的
再次,我们不知道用户在任何情况下将提供什么。eval()并且 exec()将执行我们养活他们。用户可以构建一个字符串,以便它运行其他Python函数,以便可能清除所有数据,公开您的密钥,转储数据库或执行其他恶意操作。
一个危险的例子
与上一个例子相关,假设你eval的字符串如下所示:"os.system(’rm -rf /’) # dangerous!"。它也可以清除所有文件。
使用什么
这取决于。如果您正在尝试使用,eval或者exec可能有更好的方法来完成您要做的工作。这些功能可以以许多不同的方式使用,因此提供涵盖所有用例的替代方案是具有挑战性的。
如果您正在使用它们来执行序列化/反序列化,则可能会使用另一种格式(如可以加载json模块的JSON)。
如果你必须使用它们...
再次,逃避您的投入。您还可以禁用内置功能,使得更难制作恶意输入,Ned Batchelder在Eval中所覆盖的内容 真的很危险。