Why is this an issue?
XML standard allows the use of entities, declared in the DOCTYPE of the document, which can be internal or external.
When parsing the XML file, the content of the external entities is retrieved from an external storage such as the file system or network, which may
lead, if no restrictions are put in place, to arbitrary file disclosures or server-side request forgery (SSRF) vulnerabilities.
It’s recommended to limit resolution of external entities by using one of these solutions:
- If DOCTYPE is not necessary, completely disable all DOCTYPE declarations.
- If external entities are not necessary, completely disable their declarations.
- If external entities are necessary then:
- Use XML processor features, if available, to authorize only required protocols (eg: https).
- And use an entity resolver (and optionally an XML Catalog) to resolve only trusted entities.
Noncompliant code example
System.Xml.XmlDocument
// .NET Framework < 4.5.2
XmlDocument parser = new XmlDocument(); // Noncompliant: XmlDocument is not safe by default
parser.LoadXml("xxe.xml");
or
// .NET Framework 4.5.2+
XmlDocument parser = new XmlDocument();
parser.XmlResolver = new XmlUrlResolver(); // Noncompliant: XmlDocument.XmlResolver configured with XmlUrlResolver that makes it unsafe
parser.LoadXml("xxe.xml");
System.Xml.XmlTextReader
// .NET Framework < 4.5.2
XmlTextReader reader = new XmlTextReader("xxe.xml"); // Noncompliant: XmlTextReady is not safe by default
while (reader.Read())
{ ... }
or
// .NET Framework 4.5.2+
XmlTextReader reader = new XmlTextReader("xxe.xml");
reader.XmlResolver = new XmlUrlResolver(); // Noncompliant: XmlTextRead.XmlResolver configured with XmlUrlResolver that makes it unsafe
while (reader.Read())
{ ... }
System.Xml.XmlReader
// .NET Framework 4.5.2+
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;
settings.XmlResolver = new XmlUrlResolver();
XmlReader reader = XmlReader.Create("xxe.xml", settings); // Noncompliant: XmlReader is safe by default and becomes unsafe if DtdProcessing = Parse and XmlResolver is not null
while (reader.Read())
{ ... }
System.Xml.XPath.XPathDocument
// prior to .NET 4.5.2
XPathDocument doc = new XPathDocument("example.xml"); // Noncompliant
XPathNavigator nav = doc.CreateNavigator();
string xml = nav.InnerXml.ToString();
Compliant solution
System.Xml.XmlDocument
XmlDocument parser = new XmlDocument();
parser.XmlResolver = null; // Compliant: XmlResolver has been set to null
parser.LoadXml("xxe.xml");
or
XmlDocument parser = new XmlDocument(); // Compliant: XmlDocument is safe by default in .NET Framework 4.5.2+ because XmlResolver is set by default to null
parser.LoadXml("xxe.xml");
System.Xml.XmlTextReader
// .NET 4.5.2+
XmlTextReader reader = new XmlTextReader("xxe.xml"); // Compliant: XmlTextReader is safe by default in .NET Framework 4.5.2+ because XmlResolver is set by default to null
while (reader.Read())
{ ... }
// .NET 4.0 to .NET 4.5.1
XmlTextReader reader = new XmlTextReader("xxe.xml");
reader.DtdProcessing = DtdProcessing.Prohibit; // Compliant: XmlTextReader is safe by default in .NET Framework 4.5.2+ because XmlResolver is set by default to null
// < .NET 4.0
XmlTextReader reader = new XmlTextReader(stream);
reader.ProhibitDtd = true; // Compliant: default is false
System.Xml.XmlReader
XmlReader reader = XmlReader.Create("xxe.xml"); // Compliant: XmlReader is safe by default
while (reader.Read())
{ ... }
System.Xml.XPath.XPathDocument
// prior to .NET 4.5.2
XmlReader reader = XmlReader.Create("example.xml");
XPathDocument doc = new XPathDocument(reader); // Compliant: XPathDocument is safe when being given a safe XmlReader
XPathNavigator nav = doc.CreateNavigator();
string xml = nav.InnerXml.ToString();
Resources