XML 外部实体扩展¶
ID: py/xxe
Kind: path-problem
Security severity: 9.1
Severity: error
Precision: high
Tags:
- security
- external/cwe/cwe-611
- external/cwe/cwe-827
Query suites:
- python-code-scanning.qls
- python-security-extended.qls
- python-security-and-quality.qls
使用配置较弱的 XML 解析器解析不受信任的 XML 文件可能会导致 XML 外部实体 (XXE) 攻击。这种类型的攻击使用外部实体引用来访问系统上的任意文件,执行拒绝服务 (DoS) 攻击或服务器端请求伪造。即使解析结果未返回给用户,DoS 攻击仍然可能发生,并且带外数据检索技术可能允许攻击者窃取敏感数据。
建议¶
防止 XXE 攻击的最简单方法是在解析不受信任的数据时禁用外部实体处理。如何做到这一点取决于所使用的库。请注意,某些库,例如 Python 3 标准库中最近版本的 XML 库,默认情况下会禁用实体扩展,因此除非您显式启用实体扩展,否则无需采取任何进一步的措施。
我们建议使用 defusedxml PyPI 包,该包旨在防止 XML 攻击(包括 XXE 和 XML 炸弹)。
示例¶
以下示例使用 lxml
XML 解析器来解析字符串 xml_src
。该字符串来自不受信任的来源,因此这段代码容易受到 XXE 攻击,因为来自 lxml.etree
的 默认解析器 允许解析本地外部实体。
from flask import Flask, request
import lxml.etree
app = Flask(__name__)
@app.post("/upload")
def upload():
xml_src = request.get_data()
doc = lxml.etree.fromstring(xml_src)
return lxml.etree.tostring(doc)
为了防止使用 lxml
库进行 XXE 攻击,您应该创建一个解析器,将 resolve_entities
设置为 false
。这意味着不会进行任何实体扩展,尽管仍然允许使用标准的预定义实体,例如 >
,用于在 XML 元素文本中写入 >
。
from flask import Flask, request
import lxml.etree
app = Flask(__name__)
@app.post("/upload")
def upload():
xml_src = request.get_data()
parser = lxml.etree.XMLParser(resolve_entities=False)
doc = lxml.etree.fromstring(xml_src, parser=parser)
return lxml.etree.tostring(doc)
参考资料¶
OWASP: XML 外部实体 (XXE) 处理.
Timothy Morgen: XML 架构、DTD 和实体攻击 - 已知技术的纲要.
Timur Yunusov, Alexey Osipov: XML 带外数据检索.
Python 3 标准库: XML 漏洞.
Python 2 标准库: XML 漏洞.
PortSwigger: XML 外部实体 (XXE) 注入.
通用弱点枚举: CWE-611.
通用弱点枚举: CWE-827.