简评:编写安全代码很困难,当你学习一个编程语言、模块或框架时,你会学习其使用方法。 在考虑安全性时,你需要考虑如何避免被滥用,Python
也不例外,即使在标准库中,也存在用于编写应用的不良实践。然而,许多 Python 开发人员却根本不知道它们。
接上篇
- 解析 XML(Parsing XML)
如果你的应用程序要加载、解析 XML 文件,则你可能正在使用 XML 标准库模块。通过 XML 的攻击大多是 DoS 风格(旨在使系统崩溃而不是泄露数据),这些攻击十分常见,特别是在解析外部(即不可信任的)XML 文件时。
其中有个「billion laughs」,因为他的 payload 通常包含很多(十亿)「lols」。基本上,这个原理是可以在 XML 中使用参照实体,所以当解析器将这个 XML 文件加载到内存中时,它会消耗数 G 大小的内存(RAM)。
试试看,如果你不相信我的话 :-)
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">]>
&lol9;
另一些攻击使用外部实体扩展。XML 支持从外部 URL 引用实体,XML解析器通常会毫无疑问地获取并加载该资源。「攻击者可以规避防火墙并访问受限制的资源,因为所有请求都是由内部可信的 IP 地址创建的,而不是来自外部。」
需要考虑的另一种情况是依赖的第三方软件包需要解码 XML ,例如配置文件、远程 API。你甚至可能不知道某个依赖关系会将这些类型的攻击置之不理。
修复:
使用 defusedxml 替换标准库模块,它增加了针对这些类型攻击的安全防护。
- 受污染的 site-packages 或 import 路径
Python 的 import 系统非常灵活,当你想要为测试写猴子补丁或重载核心功能时,这是非常棒的。
但这却是 Python 中最大的安全漏洞之一。
安装第三方软件包,无论是在虚拟环境中还是全局(通常不鼓励)都会让你看到这些软件包中的安全漏洞。有一些发布到 PyPi 的软件包与流行的软件包具有相似的名称,但是却执行了任意代码。
需要考虑的另一种情况是依赖的依赖,他们可能包含漏洞,他们也可以通过导入系统覆盖Python 中的默认行为。
修复:
看看 http://PyUp.io 及其安全服务,为所有应用程序使用虚拟环境,并确保全局的 site-packages 尽可能干净,检查包签名。
- 序列化 Pickles
反序列化 pickle 数据和 YAML 一样糟糕。Python 类可以声明一个 reduce 方法,该方法返回一个字符串,或一个可调用的元组以及使用 pickle 序列化时调用的参数。攻击者可以使用它来包含对其中一个子进程模块的引用,以在主机上运行任意命令。
修复:
切勿使用 pickle 反序列化不受信任或未经身份验证来源的数据。改用另一种序列化模式(如JSON)。
- 使用系统 Python 运行时并且不修复它
大多数 POSIX 系统都自带有一个 Python 2 版本(通常是旧版本)。
有时候 Python(即 CPython 是用 C 语言编写的) 解释器本身存在漏洞, C 中的常见安全问题与内存分配有关,所以大多是缓冲区溢出错误,CPython 多年来一直存在一些溢出漏洞,每个漏洞都在后续版本中进行了修复。也就是说,如果及时升级 python 运行时,就很安全。
修复:
为生产应用程序安装最新版本的 Python,并及时安装修复更新!
- 不修复依赖关系
类似于不修补 python 运行时,还需要定期修补依赖关系。
在 PyPi 的软件包中「钉住」 Python 软件包版本的做法是很糟糕的,目的是「这些是能正常工作的版本」,所以每个人都不升级它。
上面提到的代码中的所有漏洞在第三方包中存在时同样重要,这些软件包的开发人员每时每刻都在修复安全问题。
修复:
使用像 PyUp.io 这样的服务来检查更新,向应用程序提出 pr,并运行测试以保持软件包是最新的。
原文:10 common security gotchas in Python and how to avoid them