编写安全代码很难。当您学习一种语言,一种模块或一种框架时,您将了解应该如何使用它。考虑安全性时,您需要考虑如何滥用它。Python也不例外,即使在标准库中,也记录了编写强化应用程序的不良做法。但是,当我与许多Python开发人员交谈时,他们根本不了解他们。今天本文主要介绍的是Python中的10个常见安全陷阱以及避免方法的信息。
1.输入注入
注入攻击非常广泛并且确实很常见,并且注入的类型很多。它们影响所有语言,框架和环境。
SQL注入是直接编写SQL查询而不是使用ORM并将字符串文字与变量混合的地方。我读了很多代码,其中“转义引号”被认为是解决方法。不是,熟悉此备忘单可进行SQL注入的所有复杂方式。
您可以在使用popen,子进程,os.system并从变量获取参数的任何时候调用命令注入。调用本地命令时,有人可能会将这些值设置为恶意内容。
想象一下这个简单的脚本[credit]。您使用用户提供的文件名调用子进程:
import subprocess
def transcode_file(request, filename):
command = 'ffmpeg -i "{source}" output_file.mpg'.format(source=filename)
subprocess.call(command, shell=True) # a bad idea!
避免方法:
如果使用的是Web框架随附的实用程序,则对输入内容进行清理。除非您有充分的理由,否则不要手动构造SQL查询。大多数ORM具有内置的消毒方法。
对于外壳,请使用shlex模块正确地转义输入。
2.解析XML
如果您的应用程序曾经加载并解析XML文件,则很可能您正在使用XML标准库模块之一。通过XML有一些常见的攻击。大多是DoS风格的。这些攻击很常见,尤其是当您解析外部XML文件时。
其中之一被称为“十亿个笑声”,因为有效载荷通常包含很多“笑声”。基本上,您的想法是可以使用XML进行引用实体,因此,当您不使用XML的解析器尝试将此XML文件加载到内存中时,它将占用数GB的RAM。
另一种攻击是使用外部实体扩展。XML支持从外部URL引用实体,XML解析器通常会毫无限制地获取和加载该资源。“攻击者可以绕过防火墙并获得对受限资源的访问权限,因为所有请求都是从内部可信赖的IP地址发出的,而不是从外部发出的。”
要考虑的另一种情况是您依赖于解码XML的第三方包,例如配置文件,远程API。您甚至可能没有意识到,您的依赖项之一使自己容易受到这些类型的攻击。
避免方法:
使用defusedxml替代标准库模块。它增加了针对这些类型攻击的安全防护。
3.声明
不要使用assert语句来防止用户不应访问的代码段。以这个简单的例子
def foo(request,user):
断言user.is_admin,“用户无权访问”
#安全代码...
现在,默认情况下,Python以__debug__true的身份执行,但是在生产环境中,通常会运行优化。这将跳过assert语句,并直接转到安全代码,而不管用户is_admin与否。
避免方法:
仅使用assert语句与其他开发人员进行通信,例如在单元测试中或在防止API使用不正确的情况下。
4.定时攻击
定时攻击本质上是一种通过定时比较提供的值所花费的时间来揭示行为和算法的方法。定时攻击需要精度,因此它们通常无法在高延迟的远程网络上工作。由于大多数Web应用程序涉及可变的延迟,因此在HTTP Web服务器上编写定时攻击几乎是不可能的。
但是,如果您有一个提示输入密码的命令行应用程序,则攻击者可以编写一个简单的脚本来确定将其值与实际机密进行比较所花费的时间。
避免方法:
使用secrets.compare_digest ,在Python 3.5引入了比较密码和其他个人价值。
5.污染的站点包或导入路径
Python的导入系统非常灵活。当您尝试为测试编写猴子补丁或重载核心功能时,这很棒。
但是,这是Python中最大的安全漏洞之一。
无论在虚拟环境中还是在全局站点程序包(通常不鼓励使用)中,将第3方程序包安装到您的站点程序包中都会使您面临这些程序包中的安全漏洞。
出现了一些与流行的软件包名称相似但发布到PyPi的软件包,但是会执行任意代码。幸运的是,最大的事件没有害处,只是“指出”该问题并未得到真正解决。
要考虑的另一种情况是您的依存关系(依此类推)。它们可能包括漏洞,也可能会通过导入系统覆盖Python中的默认行为。
避免方法:
审核您的包裹。查看PyUp.io及其安全服务。对所有应用程序使用虚拟环境,并确保您的全局站点程序包尽可能干净。检查包签名。
6.临时文件
要在Python中创建临时文件,通常需要使用mktemp()函数生成文件名,然后使用该名称创建文件。“这是不安全的,因为在第一个进程调用到随后尝试创建该文件之间的时间内,不同的进程可能会使用该名称mktemp()创建文件。” [1]这意味着它可能会欺骗您的应用程序以加载错误的数据或公开其他临时数据。
如果调用不正确的方法,Python的最新版本将发出运行时警告。
避免方法:
使用该tempfile 模块,并 mkstemp在需要生成临时文件时使用。
7.使用yaml.load
引用PyYAML文档:
警告:yaml.load从不可信来源收到的任何数据都无法打电话。yaml.load具有强大的功能pickle.load,因此可以调用任何Python函数。”
这个美丽的例子在流行的Python项目Ansible中找到。您可以为Ansible Vault提供此值作为有效YAML。它os.system()使用文件中提供的参数进行调用。
python/object/apply:os.system ["cat /etc/passwd"]
因此,从用户提供的值有效加载YAML文件可让您敞开大门进行攻击。
避免方法:
yaml.safe_load除非您有充分的理由,否则几乎总是使用。
8.泡菜
反序列化泡菜数据与YAML一样糟糕。Python类可以声明一个魔术方法__reduce__,该方法返回一个字符串,或者声明一个具有可调用项的元组,以及在腌制时要调用的参数。攻击者可以使用它来包含对子流程模块之一的引用,以在主机上运行任意命令。
这个奇妙的示例显示了如何腌制在Python 2中打开外壳程序的类。还有更多有关如何利用腌制的示例。
导入cPickle
导入子进程
导入base64
类RunBinSh(object):
def __reduce __(self):
return(subprocess.Popen ,(('/ bin / sh',),))
打印base64.b64encode(cPickle.dumps(RunBinSh()) )
避免方法:
切勿从不可信或未经身份验证的源中获取数据。请改用其他序列化模式,例如JSON。
9.使用系统Python运行时而不进行修补
大多数POSIX系统都带有Python 2版本。通常是一个旧版本。
由于“ Python”即CPython。是用C编写的,因此Python解释器本身有时会有漏洞。C语言中的常见安全问题与内存分配有关,因此存在缓冲区溢出错误。
多年来,CPython拥有许多溢出或溢出漏洞,每个漏洞都已在后续发行版中进行了修补和修复。
所以你很安全。也就是说,如果您修补运行时。
这是2.7.13及以下版本的示例,它是一个整数溢出漏洞,可启用代码执行。这几乎是Ubuntu 17之前的任何未修补版本。
避免方法:
为您的生产应用程序安装最新版本的Python,然后对其进行修补。
10.不打补丁
与不修补运行时类似,您还需要定期修补依赖项。
我发现在PyPi中“避免方法” Python软件包版本的做法令人恐惧。这个想法是“ 这些是可行的版本 ”,因此每个人都将其保留。
我上面提到的代码中的所有漏洞在应用程序使用的程序包中都存在时同样重要。这些软件包的开发人员修复了安全性问题。
避免方法:
使用PyUp.io之类的服务来检查更新,向应用程序提出拉/合并请求并运行测试以使程序包保持最新。
使用InSpec之类的工具可以在生产环境中验证安装的版本,并确保修补了最小的版本或版本范围。
以上就是关于Python中的10个常见安全陷阱以及避免方法的全部内容介绍,想了解更多关于Python的信息,请继续关注我们。