本文目录导读:

- Java (JAXP, DOM, SAX, StAX)
- Python (lxml)
- PHP (SimpleXML, DOMDocument)
- .NET (C#)
- Node.js (sax, libxmljs, fast-xml-parser)
- 通用安全配置原则(即使代码已写)
- 特殊场景:SOAP、REST API 或第三方库
- 总结:最简单的“万能”方法
XML外部实体注入(XXE)是一种利用XML解析器处理外部实体时存在的安全漏洞,要禁用外部实体,核心思路是在XML解析器中关闭外部实体加载和DTD处理功能,根据你使用的语言和解析库,具体配置不同,以下是常见语言/库的禁用方法:
Java (JAXP, DOM, SAX, StAX)
关键点: 设置 DocumentBuilderFactory、SAXParserFactory 或 XMLInputFactory 的相应特性。
示例(DocumentBuilderFactory):
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// 禁用外部实体(推荐)
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
// 或者更精细控制:禁用外部通用实体和参数实体
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
DocumentBuilder builder = dbf.newDocumentBuilder();
Python (lxml)
关键点: 使用 parser 对象时禁用 load_dtd 和 entity 解析。
from lxml import etree
parser = etree.XMLParser(
load_dtd=False, # 禁止加载DTD
no_network=True, # 禁止网络访问外部实体
resolve_entities=False # 禁止解析外部实体
)
tree = etree.parse(xml_file, parser)
PHP (SimpleXML, DOMDocument)
关键点: 设置 LIBXML_NOENT 或 LIBXML_NONET(推荐用 libxml_disable_entity_loader,但PHP 8+已弃用)。
// 方法一(纯PHP 7及以下兼容) $old = libxml_disable_entity_loader(true); // 禁用外部实体加载 $xml = simplexml_load_string($xmlContent); libxml_disable_entity_loader($old); // 方法二(推荐,使用LIBXML选项) $xml = simplexml_load_string($xmlContent, 'SimpleXMLElement', LIBXML_NOENT | LIBXML_NONET); // 或者 $dom = new DOMDocument(); $dom->loadXML($xmlContent, LIBXML_NOENT | LIBXML_NONET);
.NET (C#)
关键点: 将 XmlReaderSettings 的 DtdProcessing 设置为 Prohibit 或 Ignore。
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Prohibit; // 完全禁止DTD处理
// 或 settings.DtdProcessing = DtdProcessing.Ignore; // 忽略DTD但不报错
using (XmlReader reader = XmlReader.Create(xmlStream, settings))
{
while (reader.Read()) { /* 安全处理 */ }
}
Node.js (sax, libxmljs, fast-xml-parser)
关键点: 关闭实体解析。
- fast-xml-parser (推荐):
const parser = new XMLParser({ processEntities: false, // 不处理实体(包括外部实体) // 或禁止外部实体加载 // entity: { denyList: ['*'] } }); const json = parser.parse(xmlString); - sax-js:
var sax = require("sax"); var parser = sax.parser(true, { lowercase: true }); // sax没有直接禁用外部实体的选项,需手动过滤错误
通用安全配置原则(即使代码已写)
- 禁止DTD声明:大多数XXE攻击依赖DTD中的
<!ENTITY>声明,直接拒绝DTD最为简单。 - 禁止外部引用协议:如
file://,http://,php://等。 - 使用白名单解析:如果必须允许外部实体,只允许可信任的源(如本地
file:路径白名单)。
特殊场景:SOAP、REST API 或第三方库
- SOAP: 在Web服务框架中设置解析器(如Spring的
DocumentBuilderFactory)。 - JAXB: 设置
Unmarshaller的解析器。 - Logstash/Elasticsearch: 避免使用默认XML解析器,改用安全配置。
最简单的“万能”方法
如果你能控制XML解析器的创建,直接完全禁用DTD处理(disallow-doctype-decl 或 DtdProcessing.Prohibit)通常最为彻底,因为外部实体声明必须通过DTD来定义,只有当你确实需要解析业务所需的DTD片段时,才选择更细粒度的禁用外部实体功能。