XElement.Parse处理XML字符串时是否会处理外部DTD?静态代码分析告警疑问
静态代码分析工具在调用XElement.Parse的代码行上报出无限制文档类型的安全问题,该方法的输入为某API调用的结果。
根据文档,XDocument.Load和XElement.Load默认禁止DTD处理,加载带有外部DTD的XML会抛出「出于安全原因,此XML文档中禁止DTD」的运行时异常。但使用XElement.Parse处理相同的XML字符串却未抛出异常,文档显示它基于标准XmlReader.Create实现,因此预期会出现相同异常。
想明确以下问题:
XElement.Parse是否会处理DTD,还是仅忽略XML声明与DTD信息?- 能否将该安全告警标记为误报,还是应修改代码使用XmlReader并显式禁止DTD处理?
抛出异常的代码示例
var xml = @"<?xml version=""1.0"" standalone=""no""?> <!DOCTYPE serviceResponse SYSTEM ""serviceResponse.dtd""> <serviceResponse> <item> <name>item 1</name> </item> </serviceResponse>"; var stringReader = new StringReader(xml); var xmlReader = XmlReader.Create(stringReader); XElement.Load(xmlReader);
异常信息
[System.Xml.XmlException: For security reasons DTD is prohibited in this XML document. To enable DTD processing set the DtdProcessing property on XmlReaderSettings to Parse and pass the settings into XmlReader.Create method.]
正常运行的代码示例
var xml = @"<?xml version=""1.0"" standalone=""no""?> <!DOCTYPE serviceResponse SYSTEM ""serviceResponse.dtd""> <serviceResponse> <item> <name>item 1</name> </item> </serviceResponse>"; XElement.Parse(xml);
解答
XElement.Parse的DTD处理行为XElement.Parse内部默认使用的XmlReaderSettings配置为DtdProcessing.Ignore,它会跳过XML中的DTD声明部分,既不会尝试加载外部DTD文件,也不会解析DTD中的实体引用,因此不会抛出异常。但它并非像XElement.Load默认行为那样禁止DTD(DtdProcessing.Prohibit)——后者会直接抛出异常阻断程序执行。告警是否为误报?
不能标记为误报。虽然XElement.Parse默认不会处理DTD,但从安全最佳实践角度,显式配置DTD处理规则能避免潜在的配置变更风险(比如未来.NET版本调整默认行为),同时也能明确代码的安全意图,符合静态代码分析的安全要求。推荐的代码修改方案
显式创建XmlReaderSettings并设置DtdProcessing.Prohibit,再通过XmlReader解析XML,确保严格禁止DTD处理:
var xml = @"<?xml version=""1.0"" standalone=""no""?> <!DOCTYPE serviceResponse SYSTEM ""serviceResponse.dtd""> <serviceResponse> <item> <name>item 1</name> </item> </serviceResponse>"; var settings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Prohibit, // 可额外添加其他安全配置,比如禁用实体引用等 }; using var stringReader = new StringReader(xml); using var xmlReader = XmlReader.Create(stringReader, settings); var element = XElement.Load(xmlReader);
这样修改后,代码会和XElement.Load的默认安全行为一致,遇到含DTD的XML时直接抛出异常,彻底阻断潜在的DTD注入风险。
内容的提问来源于stack exchange,提问作者Wouter Van Noort

