Is there a way to prevent .NET\'s XmlReader
class from expanding XML entities into their value when reading the content?
For instance, suppose the follo
XML parsing is dangerous. In some cases it allows to CVEs and Denial-of-Service attacks.
For example CVE-2016-3255
Also it was disscussed on Black Hat EU 2013
The most interested document is MLDTDEntityAttacks that provides Implementations and Recomendations for developers.
Retrieve resources:
<!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>
Back to your question.
As @Evk wrote:
By setting EntityHandling you can prevent from expanding all entities except CharEntities.
I dont know solution to prevent expand CharEntity except your own XmlReader implementation.
I think you also want prevent parsing & ' < > "
FYI how and where XmlTextReader parses CharEntity
XmlTextReader
ParseElementContent
& case
ParseText
Char entity case
ParseCharRefInline
This function finally parses numeric character entity reference (e.g.  
and á
)
ParseNumericCharRefInline
This function parses named character entity reference (& ' < > "
)
ParseNamedCharRef
One way to do that is use `XmlTextReader', like this:
using (var reader = new XmlTextReader(@"your url"))
{
// note this
reader.EntityHandling = EntityHandling.ExpandCharEntities;
while (reader.Read())
{
// here it will be EntityReference with no exceptions
}
}
If that is not an option - you can do the same with XmlReader
, but some reflection will be required (at least I don't aware of another way):
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
}
}