Prevent XmlReader from expanding XML entities

前端 未结 2 1076
说谎
说谎 2021-01-19 07:42

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

相关标签:
2条回答
  • 2021-01-19 08:26

    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 &amp; &apos; &lt; &gt; &quot;

    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. &#32; and &#x00E1;)
    ParseNumericCharRefInline


    This function parses named character entity reference (&amp; &apos; &lt; &gt; &quot;)
    ParseNamedCharRef

    0 讨论(0)
  • 2021-01-19 08:27

    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
         }
     }
    
    0 讨论(0)
提交回复
热议问题