How to identify and mitigate XXE vulnerabilities
Security vulnerabilities that are created through the serialization of sensitive data are well known, yet some developers are still falling into this trap. We will look at some basic web application safeguards that you can employ to keep your applications hardened against this growing threat. To help understand this growing problem, we will turn to the OWASP Top 10 List (a powerful awareness document for web application security based on the consensus of leading security experts and developers), and find out how XXE vulnerabilities are starting to feature more often in web app-based attacks.
Since the XML external entity injection (XXE) attack method has entered the OWASP Top 10 list, it means that the threat that this vulnerability poses has become more prevalent in recent years and warrants special attention from developers and cybersecurity professionals.
The average XXE attack starts when an unauthorized XML input that contains an external reference to entities outside of the trusted domain where the application resides. This is caused by an improperly configured XML parser and can cause serious damage to a system and to the organization that it serves. Confidential data leaks, DOS attacks, and server side forgery requests are just some of the potential threats that await a system with an XXE vulnerability.
We will look at different ways that an XXE vulnerability can be mitigated or removed from a system that is open to this threat. Most information can be found on the original OWASP link here.
What follows is a list of some of the most commonly exploited XXE vulnerabilities, as documented by OWASP.
Disable external entities (XXE)
The safest and possibly most effective way to prevent an XXE attack is to disable external entities, also called DTDs, entirely. The parser that you use will depend on the method that you use, but using a method similar to this (as suggested by OWASP’s XXE Cheat Sheet):
By disabling DTDs, application developers are also able to strengthen the parser’s ability to protect itself against DoS (denial of service) attacks like the infamous quadratic blow up attack, Billion Laughs (see code example below).
(Image courtesy of Wikipedia)
If DTDs cannot be completely disabled, then external entities must be disabled in such a way that the doctypes are specific to each individual parser, meaning that an unknown entity can’t sneak in and be executed as part of a malicious script.
What follows is a brief description of some common approaches to plugging up this vulnerability in the most commonly targeted languages.
To protect against XXE vulnerabilities in C/C++, the Enum xmlParserOption must not have the following options defined within the configuration:
- XML_PARSE_NOENT: This option expands on entities and then substitutes them with replacement text, which is where malicious attackers can insert volatile code.
- XML_PARSE_DTDLOAD: This option allows DTDs, also known as external entities, to be called and executed.
It is also recommended that you use XercesDOMParser to prevent XXE:
Java applications that use XML libraries are especially vulnerable to XXE because the default settings that are found in most Java XML parsers have XXE enabled by default. This means that using one of these parsers will require additional steps before they can be used safely, specifically by disabling XXE in your selected parser. The steps that follow will show how to disable some of the most commonly used XML parser in Java.
JAXP DocumentBuilderFactory, SAXParserFactory and DOM4J
DocumentBuilderFactory, SAXParserFactory and DOM4J XML Parsers can all be configured by utilizing the same techniques as seen in previous examples against XXE. Only the DocumentBuilderFactory example is shown below as an image.
The JAXP DocumentBuilderFactory example can be found here; it allows the developer to control whichever implementation-specific XML processor features that they wish to enable or disable. The features can either be set on the factory or the underlying XMLReader setFeature method. Each of the XML processor implementations has its own features that govern how DTDs and external entities are processed, so familiarizing yourself with them is important.
To see syntax highlighted examples and code snippets using SAXParserFactory, click here.
StAX parsers allow various properties and features to be set up and configured; one such example is XMLInputFactory. A link to their website can be found here.
An example of how a developer might protect a Java XMLInputFactory instance from XXE looks like this:
Protecting a javax.xml.transform.TransformerFactory from XXE looks like this:
Protecting a javax.xml.validation.Validator from XXE looks like this:
Protecting a javax.xml.validation.SchemaFactory from XXE looks like this:
Protecting a javax.xml.transform.sax.SAXTransformerFactory from XXE looks like this:
Protecting a Java org.xml.sax.XMLReader from XXE looks like this:
Many more Java XXE Vulnerability examples can be found here.
Information that follows relates specifically to XXE injection in .NET and is directly from the web application tester, written by Dean Fleming: https://github.com/deanf1/dotnet-security-unit-tests. This web application covers all of the current .NET XML parsers that are supported, and has test cases for each method, thus demonstrating when an implementation is safe from XXE injection and when it is vulnerable.
In the past, this information was based on James Jardine’s excellent .NET XXE article, which can be found here. It was originally able to provide more recent and detailed data than what the older article from Microsoft was able to on how XXE and XML denial of service works in .NET. However, it does have inaccuracies that the web application is able to cover.
This table lists all of the supported .NET XML parsers, as well as their default safety levels:
LINQ to XML
XElement and XDocument objects that are found in the System.Xml.Linq library are safe from XXE injection by default. This is because XElement parses only the elements within the XML file, so DTDs are ignored altogether. XDocument has DTDs disabled by default, and is only considered unsafe if it has been constructed with a different or unsafe XML parser.
System.Xml.XmlDictionaryReader is also safe by default and, when it attempts to parse the DTD, the compiler will throw an exception stating that “CData elements not valid at top level of an XML document.” It only becomes unsafe if is constructed with a different or unsafe XML parser.
Versions of the .NET Framework before version 4.5.2 contain versions of System.Xml.XmlDocument that are unsafe by default. The XmlDocument object has an XmlResolver object within it that needs to be set to null in versions older than 4.5.2. In versions 4.5.2 and up, this XmlResolver has been set to null by default. The following example shows how it is made safe:
(XmlDocument can become unsafe if you create your own nonnull XmlResolver with default or unsafe settings.)
System.Xml.XmlNodeReader objects are safe by default and will ignore DTDs, even if they are made with an unsafe parser or are wrapped in another unsafe parser.
System.Xml.XmlReader objects are safe by default and are set to have their ProhibitDtd property set to false in .NET Framework versions 4.0 and earlier. Their DtdProcessing property is also set to Prohibit in .NET versions 4.0 and later by default. .NET versions 4.5.2 and later have the XmlReaderSettings belonging to the XmlReader, which means that XmlResolver is set to null by default, which gives an extra layer of safety.
This means that XmlReader objects will only become unsafe in version 4.5.2 and up if both the DtdProcessing property is set to “Parse” and the XmlReaderSetting’s XmlResolver is set to a nonnull XmlResolver, with default/unsafe settings. If you need to enable DTD processing, instructions on how to do so safely are described here.
System.Xml.XmlTextReader is another element that is unsafe by default in .NET Framework versions prior to 4.5.2.
Prior to .NET 4.0
In .NET Framework versions prior to 4.0, DTD parsing behavior for XmlReader objects like XmlTextReader are controlled by the Boolean ProhibitDtd property found in the System.Xml.XmlReaderSettings and System.Xml.XmlTextReader classes. Set these values to true to disable inline DTDs completely.
.NET 4.0 – .NET 4.5.2
In .NET Framework version 4.0, DTD parsing behavior was changed. The ProhibitDtd property was deprecated for the new DtdProcessing property. But this has not necessarily solved the default insecurity because they didn’t change the default settings, meaning that XmlTextReader is still vulnerable to XXE upon installing it. If you set DtdProcessing to Prohibit, it will cause the runtime to throw an exception if a <!DOCTYPE> element is present in the XML. To set this value manually you must use the following:
Another option that can be used is to set the DtdProcessing property to Ignore, which will not throw an exception on encountering a <!DOCTYPE> element. Instead, it will simply skip over it and not process it. In addition, developers can also set DtdProcessing to “Parse” if they do want to allow and process inline DTDs.
.NET 4.5.2 and later
In .NET Framework versions 4.5.2 and up, XmlTextReader’s internal XmlResolver is set to null by default, making the XmlTextReader ignore DTDs by default. The XmlTextReader can become unsafe if you create your own nonnull XmlResolver with default or unsafe settings.
System.Xml.XPath.XPathNavigator is unsafe by default in the .NET Framework versions before 4.5.2. This is because IXPathNavigable objects like XmlDocument are not safe by default in versions prior to 4.5.2. You can make XPathNavigator safe by giving it a safe parser like XmlReader (which is safe by default) in the XPathDocument’s constructor. Here is an example:
System.Xml.Xsl.XslCompiledTransform (an XML transformer) is safe by default as long as the parser it has been given is safe. It is safe by default because the default parser of the Transform() methods is an XmlReader, which is also safe by default. The source code for this method can be viewed here. Some of the Transform() methods can accept an XmlReader or IXPathNavigable (e.g., XmlDocument) as an input and, if you pass in an unsafe XML parser, the Transform will also not be safe.
iOS includes the C/C++ libxml2 library that we looked at earlier, so the same applies to iOS if you are using libxml2. The version of libxml2 that is made available via iOS6 is a release that is prior to version 2.9 of libxml2 (which protects against XXE by default).
It is important to note that iOS also provides an NSXMLDocument type, which is predicated on libxml2. NSXMLDocument provides additional protection against XXE that isn’t found in libxml2 directly.
As per the ‘NSXMLDocument External Entity Restriction API’ section of: http://developer.apple.com/library/ios/#releasenotes/Foundation/RN-Foundation-iOS/Foundation_iOS5.html:
- iOS4 and earlier: All external entities are loaded by default (Unsafe).
- iOS5 and later: Only entities that don’t require network access are loaded (Safe).
In order to completely disable XXE in an instance of NSXMLDocument, in any version of iOS, developers will need to specify NSXMLNodeLoadExternalEntitiesNever when creating the NSXMLDocument.
As specified in the PHP documentation, these elements must be set when using the default PHP XML parser to prevent instances of XXE:
A description of how to abuse this in PHP function is detailed within this SensePost article, which describes a PHP based XXE vulnerability that was fixed in the social media giant, Facebook.
- OWASP XXE Prevention Cheat Sheet
- OWASP Top 10-2017 A4: XML External Entities (XXE)
- Timothy Morgan’s 2014 paper: “XML Schema, DTD, and Entity Attacks”
- FindSecBugs XXE Detection
- XXEbugFind Tool
- Testing for XML Injection (OTG-INPVAL-008)
More OWASP Cheat Sheets can be found here.