有没有办法阻止.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>á</author>
我们假设无法达到扩展aacute实体所需的外部OASIS DTD。我希望读者按顺序阅读author元素,然后是类型EntityReference
的aacute节点,最后是作者end元素,而不会抛出任何错误。我怎样才能做到这一点?
更新:我还想阻止á
等字符实体的扩展。
答案 0 :(得分: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
}
}
答案 1 :(得分:1)
XML解析很危险。在某些情况下,它允许CVE和拒绝服务攻击。
上讨论了这个问题最感兴趣的文件是MLDTDEntityAttacks 它为开发人员提供了实现和Recomendations。
检索资源:
<!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的解决方案。
我认为您还希望阻止解析& ' < > "
FYI XmlTextReader解析CharEntity的方式和位置
的 XmlTextReader的强>
ParseElementContent
& case
ParseText
Char entity case
ParseCharRefInline
此函数最终解析数字字符实体引用(例如 
和á
)
ParseNumericCharRefInline
此函数解析命名字符实体引用(& ' < > "
)
ParseNamedCharRef