CodeQL 文档

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

点击查看 CodeQL 代码库中的查询

使用配置较弱的 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);
});

参考

  • ©GitHub, Inc.
  • 条款
  • 隐私