必须禁用DTD和外部实体解析以防止XXE攻击:设置DtdProcessing.Prohibit(.NET Core/.NET 5+)或ProhibitDtd=true(.NET Framework),并设XmlResolver=null;同时限制输入长度、深度等,避免使用不安全的Load()方法。

在C#中使用 XmlReader 解析XML时,若未正确配置 XmlReaderSettings,可能遭受XML外部实体(XXE)攻击。关键在于禁用外部实体解析和DTD处理。
禁用 DTD 和外部实体解析
默认情况下,XmlReader 可能加载并解析DTD(文档类型定义)及外部实体(如 ),导致敏感文件读取或SSRF。必须显式关闭这些功能:
-
设置
ProhibitDtd = true(.NET Framework 4.0+)或DtdProcessing = DtdProcessing.Prohibit(.NET Core/.NET 5+) -
设置
XmlResolver = null,防止解析任何外部URI(包括系统标识符、实体引用)
使用安全的 XmlReaderSettings 示例
以下是最小安全配置(适用于 .NET Core 3.1+ 和 .NET 5+):
var settings = new XmlReaderSettings
{
DtdProcessing = DtdProcessing.Prohibit,
XmlResolver = null,
ValidationType = ValidationType.None // 禁用验证以避免隐式加载schema
};
using var reader = XmlReader.Create(xmlStream, settings);
// 后续调用 Read() 解析
对于 .NET Framework 4.0–4.7.x,改用:
var settings = new XmlReaderSettings
{
ProhibitDtd = true,
XmlResolver = null,
ValidationType = ValidationType.None
};
额外加固建议
仅靠禁用DTD还不够,还需注意以下实践:
-
不信任输入源:即使来自内部系统,也应视为不可信;对XML做长度、深度、节点数限制(可用
MaxCharactersInDocument、MaxCharactersFromEntities) -
避免使用过时API:不要用
XmlDocument.Load()或XDocument.Load()直接解析不受控XML,它们默认启用DTD且不易安全配置 -
启用行号与位置信息仅用于调试:生产环境可设
LineNumberOffset = 0、LinePositionOffset = 0,但非安全必需项
验证是否生效的小技巧
构造一个含外部实体的测试XML(如 ]>),用上述设置解析——若抛出 XmlException(提示“prohibited”或“DTD is prohibited”),说明防护已起效;若成功加载或静默失败,则配置有误。










