How to prevent XXE attack (XmlDocument in .NET) How to prevent XXE attack (XmlDocument in .NET) xml xml

How to prevent XXE attack (XmlDocument in .NET)


External resources are resolved using the XmlResolver provided via XmlDocument.XmlResolver property. If your XML documents **should not contain any external resource **(for example DTDs or schemas) simply set this property to null:

XmlDocument xmlDoc = new XmlDocument();xmlDoc.XmlResolver = null;xmlDoc.LoadXml(OurOutputXMLString);

If you want to filter where these URLs come from (for example to allow only certain domains) just derive your own class from XmlUrlResolver and override the ResolveUri() method. There you can check what the URL is and sanitize it (for example you can allow only URLs within your local network or from trusted sources).

For example:

class CustomUrlResovler : XmlUrlResolver{    public override Uri ResolveUri(Uri baseUri, string relativeUri)    {        Uri uri = new Uri(baseUri, relativeUri);        if (IsUnsafeHost(uri.Host))            return null;        return base.ResolveUri(baseUri, relativeUri);    }    private bool IsUnsafeHost(string host)    {        return false;     }}

Where IsUnsafeHost() is a custom function that check if the given host is allowed or not. See this post here on SO for few ideas. Just return null from ResolveUri() to save your code from this kind of attacks. In case the URI is allowed you can simply return the default XmlUrlResolver.ResolveUri() implementation.

To use it:

XmlDocument xmlDoc = new XmlDocument();xmlDoc.XmlResolver = new CustomUrlResolver();xmlDoc.LoadXml(OurOutputXMLString);

For more details about how XML external resources are resolved just read Resolving External Resources on MS Docs. If your code is more complex than this example then you should definitely read Remarks section for XmlDocument.XmlResolver property.


So its better to use

new XmlDocument { XmlResolver = null };

Interestingly from .net 4.5.2 and 4.6, the default resolver behaves differently and does not use an XmlUrlResolver upfront implicitly to resolve any urls or locations as i seen.

//In pre 4.5.2 it is a security issue.//In 4.5.2 it will not resolve any more the url references in dtd and such, //Still better to avoid the below since it will trigger security warnings.new XmlDocument(); 


Setting the XmlReaderSettings.DtdProcessing to DtdProcessing.Prohibit works totally fine in .NET 4.7.2. Here is what i used to test.

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE demo [  <!ELEMENT demo ANY >  <!ENTITY % extentity SYSTEM "https://www.hl7.org/documentcenter/public/wg/structure/CDA.xsl">  %extentity;]><test>    Some random content</test>

Saved the above content in a file and read the file from the following fragment of c# code.

XmlReaderSettings settings = new XmlReaderSettings();settings.DtdProcessing = DtdProcessing.Prohibit;settings.MaxCharactersFromEntities = 6000;//The following stream should be the filestream of the above content.XmlReader reader = XmlReader.Create(stream, settings);XmlDocument xmlDoc = new XmlDocument();xmlDoc.Load(reader);

I get the following exception.

For security reasons DTD is prohibited in this XML document. To enable DTD processing set the DtdProcessing property on XmlReaderSettings to Parse and pass the settings into XmlReader.Create method.at System.Xml.XmlTextReaderImpl.Throw(Exception e)at System.Xml.XmlTextReaderImpl.ParseDoctypeDecl()at System.Xml.XmlTextReaderImpl.ParseDocumentContent()at System.Xml.XmlLoader.LoadNode(Boolean skipOverWhitespace)at System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc)at System.Xml.XmlDocument.Load(XmlReader reader)