20.4. XML 处理模块 — Python 文档
20.4. XML 处理模块
源代码: :source:`Lib/xml/`
Python 处理 XML 的接口被分组在 xml
包中。
警告
XML 模块对于错误或恶意构造的数据并不安全。 如果您需要解析不受信任或未经身份验证的数据,请参阅 XML 漏洞 和 defusedxml 和 defusedexpat Packages 部分。
需要注意的是,xml 包中的模块要求至少有一个符合 SAX 的 XML 解析器可用。 Expat 解析器包含在 Python 中,因此 xml.parsers.expat 模块将始终可用。
xml.dom 和 xml.sax 包的文档是 DOM 和 SAX 接口的 Python 绑定定义。
XML 处理子模块是:
- xml.etree.ElementTree:ElementTree API,一个简单轻量级的 XML 处理器
- xml.dom:DOM API 定义
- xml.dom.minidom:一个最小的DOM实现
- xml.dom.pulldom:支持构建部分DOM树
- xml.sax:SAX2 基类和便利函数
- xml.parsers.expat:Expat 解析器绑定
20.4.1. XML 漏洞
XML 处理模块对于恶意构造的数据并不安全。 攻击者可以滥用 XML 特性来执行拒绝服务攻击、访问本地文件、生成与其他机器的网络连接或绕过防火墙。
下表概述了已知的攻击以及各种模块是否容易受到攻击。
种类 | 萨克斯 | 树 | 迷你世界 | 拉力 | xmlrpc |
---|---|---|---|---|---|
十亿笑声 | 易受攻击的 (1) | 易受攻击的 (1) | 易受攻击的 (1) | 易受攻击的 (1) | 易受攻击的 (1) |
二次爆发 | 易受攻击的 (1) | 易受攻击的 (1) | 易受攻击的 (1) | 易受攻击的 (1) | 易受攻击的 (1) |
外部实体扩展 | 保险箱 (5) | 保险箱 (2) | 保险箱 (3) | 保险箱 (5) | 保险箱 (4) |
DTD检索 | 保险箱 (5) | 安全 | 安全 | 保险箱 (5) | 安全 |
减压炸弹 | 安全 | 安全 | 安全 | 安全 | 易受伤害的 |
- Expat 2.4.1 及更新版本不易受到“十亿笑声”和“二次爆发”漏洞的影响。 由于可能依赖系统提供的库,项目仍被列为易受攻击的项目。 勾选
pyexpat.EXPAT_VERSION
。 - xml.etree.ElementTree 不会扩展外部实体并在实体出现时引发
ParserError
。 - xml.dom.minidom 不扩展外部实体,只是逐字返回未扩展的实体。
xmlrpclib
不扩展外部实体并省略它们。- 自 Python 3.6.7 起,默认情况下不再处理外部通用实体。
- 十亿笑/指数实体扩张
- Billion Laughs 攻击(也称为指数实体扩展)使用多层嵌套实体。 每个实体多次引用另一个实体,最终的实体定义包含一个小字符串。 指数扩展会产生几 GB 的文本并消耗大量内存和 CPU 时间。
- 二次膨胀实体扩展
- 二次爆发攻击类似于 亿笑 攻击; 它也滥用实体扩展。 它不是嵌套实体,而是一遍又一遍地重复一个包含数千个字符的大型实体。 这种攻击不如指数情况有效,但它避免触发禁止深度嵌套实体的解析器对策。
- 外部实体扩展
- 实体声明可以包含的不仅仅是用于替换的文本。 它们还可以指向外部资源或本地文件。 XML 解析器访问资源并将内容嵌入到 XML 文档中。
- DTD检索
- 一些 XML 库,如 Python 的 xml.dom.pulldom 从远程或本地位置检索文档类型定义。 该功能与外部实体扩展问题具有类似的含义。
- 减压炸弹
- 解压炸弹(又名 ZIP 炸弹)适用于所有可以解析压缩 XML 流的 XML 库,例如 gzipped HTTP 流或 LZMA 压缩文件。 对于攻击者来说,它可以将传输的数据量减少三个或更多。
PyPI 上的 defusedxml 文档包含有关所有已知攻击向量的更多信息,包括示例和参考。
20.4.2. 这defusedxml和defusedexpat套餐
defusedxml 是一个纯 Python 包,它修改了所有 stdlib XML 解析器的子类,以防止任何潜在的恶意操作。 对于解析不受信任的 XML 数据的任何服务器代码,建议使用此包。 该软件包还附带示例漏洞利用和有关更多 XML 漏洞利用(例如 XPath 注入)的扩展文档。
defusedexpat 提供了一个修改的 libexpat 和一个补丁的 pyexpat
模块,这些模块具有对抗实体扩展 DoS 攻击的对策。 defusedexpat
模块仍然允许合理且可配置的实体扩展量。 这些修改可能包含在 Python 的某些未来版本中,但不会包含在 Python 的任何错误修复版本中,因为它们破坏了向后兼容性。