XML注入风险可通过安全配置XmlReader/XDocument、禁用DTD与外部实体、避免XPath拼接及不执行用户数据来规避。关键在于不将不可信内容当代码执行,而非法防“XML注入”本身。

用 XmlReader 或 XDocument.Load() 配合验证,不拼接、不反射、不执行动态 XPath,就能基本避开 XML 注入风险。关键不是“防注入”,而是避免把不可信内容当代码执行。
用 XmlReader 流式读取,不解析实体
XmlReader 默认禁用 DTD 和外部实体(.NET Core / .NET 5+ 默认安全),但旧版 .NET Framework 需手动配置:
- 创建
XmlReaderSettings,设DtdProcessing = DtdProcessing.Prohibit - 关闭
XmlResolver:设XmlResolver = null - 再用
XmlReader.Create(stream, settings)读取
这样可防止 XXE(XML 外部实体)攻击,也避免实体展开导致的内存/服务端请求问题。
用 XDocument 时禁用 DTD 解析
XDocument.Load() 底层仍走 XmlReader,所以同样要传入安全的 XmlReaderSettings:
- 不要直接写
XDocument.Load(xmlPath) - 改用
XDocument.Load(XmlReader.Create(fileStream, safeSettings)) - 若从字符串加载,用
StringReader包一层再传给XmlReader.Create
别用 XPath 查询未过滤的用户输入
XPath 表达式拼接是常见隐患。例如:$"/root/user[@id='" + userId + "']" —— 这等于把攻击面交给了用户。
- 优先用 LINQ to XML(如
doc.Root.Elements("user").FirstOrDefault(x => x.Attribute("id")?.Value == userId)) - 若必须用 XPath,用
XPathSelectElement(doc, xpath, namespaceManager),且确保xpath是硬编码或白名单枚举值 - 绝不将用户输入直接插进 XPath 字符串
不信任任何属性值和文本节点内容
XML 数据本身不是“代码”,但若你把它当代码用,就出问题。比如:
- 把
node.Attribute("type").Value当作类名去反射加载 —— 可能触发任意类型实例化 - 把
node.Value当作 SQL 片段拼接 —— 引发 SQL 注入 - 把
node.Attribute("url").Value直接用于HttpClient.GetAsync()—— 可能外连恶意地址
这些不是 XML 注入,而是业务逻辑误用。应对方式是:校验 + 白名单 + 转义(如输出到 HTML 时用 WebUtility.HtmlEncode)。
基本上就这些。XML 本身没有“注入漏洞”,危险来自解析器配置不当、XPath 拼接、或把数据当指令执行。关掉 DTD、不用拼接、不反射用户值,就稳了。










