XML external entity injection (XXE)
Injected untrusted data into an XML parser
Select your ecosystem
What is XXE?
XML external entity injection (XXE) is an attack where untrusted data is provided to a misconfigured XML parser.
XML structures data by using tags, and provides a rigid schema mechanism that describes the nesting, presence, and type of tags. For example, XML is used in communicating data between client and server, or to locally serialize and store data.
The XML standard has a concept called an “entity”, which represents a unit of data and there are many different types of entities in the XML specification. There is a type of custom entity called an “XML External Entity" denoted by the use of the SYSTEM
keyword. The entity specifies a URL where the entity is defined, using either HTTP or file protocols. External entities can be used to retrieve both remote and local files.
If an XML parser is configured to allow external entities, attackers can take advantage of this to access internal resources, including the server’s file system and other connected systems.
About this lesson
In this lesson, we will cover how to conduct an XXE injection attack, why the attack works, and how to prevent it from happening. We’ll explore the website of a fictional essential oils company, “Oliver’s Oils”, exploit the XXE injection vulnerability, and learn about what happened under the hood by diving into the code. Last but not least, we will fix the application so that it’s no longer vulnerable.
The OWASP Top 10 (2021) is the leading standard for awareness of the most critical web application security issues. Number 5 on the list is security misconfigurations, which now include XXE. Let's walk through an example of how we might discover and initiate an XXE attack.
What happened?
In the example above, the “Oliver’s Oils” web application trusted the XML input we provided when we intercepted and edited the POST
request. By injecting our custom external entity, the XML parser processed the entity and retrieved the contents of the /etc/passwd
file, and then displayed the contents of the file along with the user’s favorites. This was possible because the XML parser that the web application uses has not disabled the use of external entities.
It’s worth noting that we aren’t just limited to local system files. Sometimes getting the response reflected in the web app, as we did in the above example, isn’t possible due to how the application works. In those cases, to exfiltrate the data, attackers can insert a remote location in the SYSTEM
entity.
The vulnerable piece of code in our JavaScript app looks like:
The web application uses the libxml
library as its parser library, as NodeJS doesn’t provide a native XML parser. The issue in this code is calling the XML parser with the noent:true
option which allows for external entities.
The code above uses the built in SimpleXMLElement
class, which resolves entities by default.
The safest way to mitigate XXE attacks in most frameworks is by disabling document type definitions completely. This will remove the ability to create custom entities. If this isn’t an option for your application, you’ll need to disable external entities and external document type declarations, depending on the parser in use.
In our situation, the parser libxmljs
actually disables external entities by default! The noent:true
option included when parsing the XML actually enabled it. So all we need to do is remove it!
Test your knowledge!
Keep learning
- You can also have a look at this great video explanation on YouTube
- Read about High-severity XML External Entities (XXE) vulnerabilities found in the Nokogiri library in our blog
- Are you curious how to configure Java to prevent XXE vulnerabilities? We have a great guide!
- And of course don’t forget to check out the XXE Cheat Sheet from OWASP