【问题标题】:Prevent XmlReader from expanding XML entities防止 XmlReader 扩展 XML 实体
【发布时间】:2017-03-13 13:43:22
【问题描述】:

有没有办法防止 .NET 的 XmlReader 类在读取内容时将 XML 实体扩展为它们的值?

例如,假设使用以下 XML 作为输入:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE author PUBLIC "ISO 8879:1986//ENTITIES Added Latin 1//EN//XML" "http://www.oasis-open.org/docbook/xmlcharent/0.3/iso-lat1.ent" >
<author>&aacute;</author>

让我们假设无法访问扩展急性实体所需的外部 OASIS DTD。我希望读者按顺序阅读作者元素,然后是EntityReference 类型的急性节点,最后是作者结束元素,而不会引发任何错误。我怎样才能做到这一点?

更新:我还想防止&amp;#x00E1;等字符实体的扩展。

【问题讨论】:

  • 什么.net框架版本?
  • @galakt .NET 4.5

标签: c# .net xml dtd xmlreader


【解决方案1】:

一种方法是使用“XmlTextReader”,如下所示:

using (var reader = new XmlTextReader(@"your url"))
{
    // note this
    reader.EntityHandling = EntityHandling.ExpandCharEntities;
    while (reader.Read())
    {
        // here it will be EntityReference with no exceptions
    }
}

如果这不是一个选项 - 你可以对 XmlReader 做同样的事情,但需要一些反思(至少我不知道其他方式):

using (var reader = XmlReader.Create(@"your url", new XmlReaderSettings() {
    DtdProcessing = DtdProcessing.Ignore // or Parse
})) {
     // get internal property which has the same function as above in XmlTextReader
     reader.GetType().GetProperty("EntityHandling", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(reader, EntityHandling.ExpandCharEntities);
     while (reader.Read()) {
          // here it will be EntityReference with no exceptions
     }
 }

【讨论】:

  • 这与我正在寻找的非常接近,但我也想防止 char 实体的扩展。 EntityHandling 枚举的值也不允许这种情况。
  • @GabrielS 我知道您可能不想扩展实体,但为什么不扩展 char 实体?
  • 我正在处理的应用程序需要控制所有 XML 实体的扩展,因为它为每个实体执行一些自定义处理。这就是为什么它需要从XmlReader 接收未扩展的实体引用而不是扩展结果。
  • 我不确定 XmlReader 或 XmlTextReader 是否可行。也许如果创建自定义 XmlReader 并将大多数功能委托给默认的...
【解决方案2】:

XML 解析是危险的。在某些情况下,它允许 CVE 和拒绝服务攻击。

例如CVE-2016-3255

也在Black Hat EU 2013上讨论过

最感兴趣的文档是MLDTDEntityAttacks 为开发人员提供实施和建议。

检索资源

<!DOCTYPE roottag [
 <!ENTITY windowsfile SYSTEM "file:///c:/boot.ini">
]>
<roottag>
 <sometag>&windowsfile;</sometag>
</roottag>

DoS

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE root
  [
  <!ENTITY a0 "test" >
  <!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;">
  <!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;">
  <!ENTITY a3 "&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;">
  <!ENTITY a4 "&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;">
  ]>
<root>&a4;</root>

回到你的问题。
正如@Evk 所写: 通过设置EntityHandling,您可以防止扩展除 CharEntities 之外的所有实体。

除了您自己的 XmlReader 实现之外,我不知道防止扩展 CharEntity 的解决方案。

我想你也想阻止解析&amp;amp; &amp;apos; &amp;lt; &amp;gt; &amp;quot;

仅供参考 XmlTextReader 解析 CharEntity 的方式和位置

XmlTextReader
ParseElementContent
& case
ParseTextChar entity case
ParseCharRefInline

该函数最终解析数字字符实体引用(例如&amp;#32;&amp;#x00E1;
ParseNumericCharRefInline


此函数解析命名字符实体引用 (&amp;amp; &amp;apos; &amp;lt; &amp;gt; &amp;quot;)
ParseNamedCharRef

【讨论】:

  • 虽然您指向代码处理实体的确切片段的链接提供了有用的见解,但重写 XmlTextReaderImpl 对我来说并不是一个真正的选择。我也看不到任何从此类继承和覆盖此特定部分的可能性,尤其是因为它甚至不是公共的。我现在看到的唯一选择是预处理 XML 以将实体更改为一些特殊的文本,这些文本不再被 XmlReader 视为实体引用,但我可以处理未扩展的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多