An XXE attack is a type of an application attack. The essence of this attack is that an insecurely configured XML parser processes external data. If an application is vulnerable to this security defect, this leads to the exposure of confidential data from the compromised device.
Note. This document describes an XXE attack. XEE attack (also called a billion laughs attack or an XML bombs attack) is described here.
XML files may contain the document type definition (DTD). DTD allows us to define and use XML entities. Entities can be fully defined inside the document (they can be a string, for example), or they can refer to external resources. That's why it's called an XXE attack: XML eXternal Entities.
External entities can be defined via URI. As a result, the XML parser processes this URI and puts the resulting content into an XML document.
The following example is an XML document that defines an external entity:
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file://D:/XXETarget.txt">
]>
<foo>&xxe;</foo>
The 'xxe' entity is defined in this XML. A developer may configure a parser to process external entities. In this case, instead of '&xxe;', a parser inserts the contents of the 'D:\XXETarget.txt' file.
Thus, an attack is possible if:
As a result, an attacker can access the file contents on a compromised device that parses an XML file. Besides, this attack may result in server-side request forgery (SSRF).
Let's assume that there's an application that accepts queries as XML files and processes items with the corresponding ID. If an XML file has the incorrect ID, the application warns the user about it.
The application works with the following XML file format:
<?xml version="1.0" encoding="utf-8" ?>
<shop>
<itemID>62</itemID>
</shop>
Let's say the following code fragment processes XML files:
static void ProcessItemWithID(String pathToXmlFile)
{
XmlReaderSettings settings = new XmlReaderSettings()
{
XmlResolver = new XmlUrlResolver(),
DtdProcessing = DtdProcessing.Parse
};
using (var fileReader = File.OpenRead(pathToXmlFile))
{
using (var reader = XmlReader.Create(fileReader, settings))
{
while (reader.Read())
{
if (reader.Name == "itemID")
{
var itemIDStr = reader.ReadElementContentAsString();
if (long.TryParse(itemIDStr, out var itemIDValue))
{
// Process item with the 'itemIDValue' value
Console.WriteLine(
$"An item with the '{itemIDValue}' ID was processed.");
}
else
{
Console.WriteLine($"{itemIDStr} is not valid 'itemID' value.");
}
}
}
}
}
}
For the XML file above, the application outputs the following string:
An item with the '62' ID was processed.
If we insert something else in the ID instead of the number (the "Hello world" string, for example), the application reports an error:
"Hello world" is not valid 'itemID' value.
The code runs as we expected. However, the following factors make the code vulnerable to XXE attacks:
Look at an XML file below. Attackers can use it to compromise this code fragment:
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file://D:/MySecrets.txt">
]>
<shop>
<itemID>&xxe;</itemID>
</shop>
An attacker declares the 'xxe' external entity in this file. The XML parser processes this entity. The 'D:/MySecrets.txt' file is on the machine where the application is running. As a result of the processing, the user gets the file contents (for example, 'This is an XXE attack target.'):
"This is an XXE attack target." is not valid 'itemID' value.
If you want to protect your code from this attack, you can prohibit processing external entities —assign the null value to the XmlResolver property. Also, you can prohibit or ignore DTD processing by writing the Prohibit / Ignore value to DtdProcessing.
An example of secure settings:
XmlReaderSettings settings = new XmlReaderSettings()
{
XmlResolver = null,
DtdProcessing = DtdProcessing.Prohibit
};
Note that the default settings of some XML parsers may vary in different versions of libraries. For example, Microsoft changed the settings of some XML parsers between .NET Framework 4.5.1 and .NET Framework 4.5.2, making them more secure by default.
Look at the following code fragment:
static void XmlDocumentTest(String pathToXml)
{
var xml = File.ReadAllText(pathToXml);
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
Console.WriteLine(doc.InnerText);
}
In .NET Framework 4.5.1 and older versions this code fragment is vulnerable to XXE attacks. XmlResolver is not null by default, thus it processes external entities.
However, this code fragment is resistant to XXE attacks in .NET Framework 4.5.2 and newer versions. XmlResolver is null by default there. As a result, external entities are not processed.
0