XML 内部实体扩展¶
ID: js/xml-bomb
Kind: path-problem
Security severity: 7.5
Severity: warning
Precision: high
Tags:
- security
- external/cwe/cwe-776
- external/cwe/cwe-400
Query suites:
- javascript-code-scanning.qls
- javascript-security-extended.qls
- javascript-security-and-quality.qls
使用配置较弱的 XML 解析器解析不受信任的 XML 文件可能容易受到利用不受控制的内部实体扩展的拒绝服务 (DoS) 攻击。
在 XML 中,所谓的内部实体是一种机制,用于为一段文本或文档的一部分引入缩写。当配置为扩展实体的解析器遇到对内部实体的引用时,它会将该实体替换为它表示的数据。替换文本本身可能包含其他实体引用,这些引用会递归扩展。这意味着实体扩展会显着增加文档大小。
如果使用启用实体扩展的解析器解析不受信任的 XML,恶意攻击者可以提交包含非常深层嵌套实体定义的文档,导致解析器花费很长时间或使用大量的内存。这有时被称为XML 炸弹攻击。
建议¶
防止 XML 炸弹攻击最安全的方法是在解析不受信任的数据时禁用实体扩展。如何做到这一点取决于所使用的库。请注意,某些库,例如最新版本的libxmljs
(但不是其 SAX 解析器 API),默认情况下会禁用实体扩展,因此除非您已明确启用实体扩展,否则无需采取进一步措施。
示例¶
以下示例使用node-expat
包提供的 XML 解析器来解析字符串xmlSrc
。如果该字符串来自不受信任的来源,则此代码可能容易受到 DoS 攻击,因为node-expat
默认情况下会扩展内部实体
const app = require("express")(),
expat = require("node-expat");
app.post("upload", (req, res) => {
let xmlSrc = req.body,
parser = new expat.Parser();
parser.on("startElement", handleStart);
parser.on("text", handleText);
parser.write(xmlSrc);
});
在撰写本文时,node-expat
并未提供控制实体扩展的方法,但可以将示例改写为使用sax
包,该包只扩展标准实体,例如&
const app = require("express")(),
sax = require("sax");
app.post("upload", (req, res) => {
let xmlSrc = req.body,
parser = sax.parser(true);
parser.onopentag = handleStart;
parser.ontext = handleText;
parser.write(xmlSrc);
});
参考¶
维基百科: 十亿次欢笑.
Bryan Sullivan: 安全简报 - XML 拒绝服务攻击与防御.
常见漏洞枚举: CWE-776.
常见漏洞枚举: CWE-400.