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